Moved Auto attack and auto fishing to ChatBots and added ChatBotAPI for entity handling

This commit is contained in:
ReinforceZwei 2020-03-23 19:59:00 +08:00 committed by ORelio
parent 8b8f3a719b
commit dbf5334758
16 changed files with 602 additions and 465 deletions

View file

@ -137,6 +137,17 @@ namespace MinecraftClient
/// <param name="data">The payload for the message</param> /// <param name="data">The payload for the message</param>
public virtual void OnPluginMessage(string channel, byte[] data) { } public virtual void OnPluginMessage(string channel, byte[] data) { }
public virtual void OnPlayerProperty(Dictionary<string, Double> prop) { }
public virtual void OnServerTpsUpdate(Double tps) { }
public virtual void OnEntityMove(Mapping.Entity entity) { }
public virtual void OnEntitySpawn(Mapping.Entity entity) { }
public virtual void OnEntityDespawn(int EntityID) { }
/* =================================================================== */ /* =================================================================== */
/* ToolBox - Methods below might be useful while creating your bot. */ /* ToolBox - Methods below might be useful while creating your bot. */
/* You should not need to interact with other classes of the program. */ /* You should not need to interact with other classes of the program. */
@ -599,6 +610,16 @@ namespace MinecraftClient
return Handler.SetTerrainEnabled(enabled); return Handler.SetTerrainEnabled(enabled);
} }
/// <summary>
/// Get entity handling status
/// </summary>
/// <returns></returns>
/// <remarks>Entity Handling cannot be enabled in runtime (or after joining server)</remarks>
public bool GetEntityHandlingEnabled()
{
return Handler.GetEntityHandlingEnabled();
}
/// <summary> /// <summary>
/// Get the current Minecraft World /// Get the current Minecraft World
/// </summary> /// </summary>
@ -764,5 +785,26 @@ namespace MinecraftClient
} }
return Handler.SendPluginChannelMessage(channel, data, sendEvenIfNotRegistered); return Handler.SendPluginChannelMessage(channel, data, sendEvenIfNotRegistered);
} }
protected Double GetServerTPS()
{
return Handler.GetServerTPS();
}
/// <summary>
/// Interact with an entity
/// </summary>
/// <param name="EntityID"></param>
/// <param name="type">0: interact, 1: attack, 2: interact at</param>
/// <returns></returns>
protected bool InteractEntity(int EntityID, int type)
{
return Handler.InteractEntity(EntityID, type);
}
protected bool UseItemOnHand()
{
return Handler.UseItemOnHand();
}
} }
} }

View file

@ -0,0 +1,99 @@
using MinecraftClient.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
class AutoAttack : ChatBot
{
private Dictionary<int, Entity> entitiesToAttack = new Dictionary<int, Entity>(); // mobs within attack range
private Dictionary<int, Entity> entitiesToTrack = new Dictionary<int, Entity>(); // all mobs in view distance
private int attackCooldown = 6;
private int attackCooldownCounter = 6;
private Double attackSpeed = 4;
private Double attackCooldownSecond;
private int attackRange = 4;
private Double serverTPS;
public override void Initialize()
{
if (!GetEntityHandlingEnabled())
{
ConsoleIO.WriteLine("[AutoAttack] Entity Handling is not enabled in the config file!");
ConsoleIO.WriteLine("Please enable it to use this bot.");
UnloadBot();
}
}
public override void Update()
{
if (attackCooldownCounter == 0)
{
attackCooldownCounter = attackCooldown;
if (entitiesToAttack.Count > 0)
{
foreach (KeyValuePair<int, Entity> a in entitiesToAttack)
{
InteractEntity(a.Key, 1);
}
}
}
else
{
attackCooldownCounter--;
}
}
public override void OnEntitySpawn(Entity entity)
{
if (entity.GetMobName() != "")
{
entitiesToTrack.Add(entity.ID, entity);
}
}
public override void OnEntityDespawn(int EntityID)
{
if (entitiesToTrack.ContainsKey(EntityID))
{
entitiesToTrack.Remove(EntityID);
}
}
public override void OnEntityMove(Entity entity)
{
if (entitiesToTrack.ContainsKey(entity.ID))
{
Double distance = Entity.CalculateDistance(GetCurrentLocation(), entity.Location);
if(distance < attackRange)
{
if(!entitiesToAttack.ContainsKey(entity.ID))
entitiesToAttack.Add(entity.ID, entity);
}
}
}
public override void OnPlayerProperty(Dictionary<string, double> prop)
{
// adjust auto attack cooldown for maximum attack damage
if (prop.ContainsKey("generic.attackSpeed"))
{
if (attackSpeed != prop["generic.attackSpeed"])
{
GetServerTPS();
attackSpeed = prop["generic.attackSpeed"];
attackCooldownSecond = 1 / attackSpeed * (serverTPS / 20.0); // server tps will affect the cooldown
attackCooldown = Convert.ToInt32(Math.Truncate(attackCooldownSecond / 0.1) + 1);
}
}
}
public override void OnServerTpsUpdate(double tps)
{
serverTPS = tps;
// re-calculate attack speed
attackCooldownSecond = 1 / attackSpeed * (serverTPS / 20.0); // server tps will affect the cooldown
attackCooldown = Convert.ToInt32(Math.Truncate(attackCooldownSecond / 0.1) + 1);
}
}
}

View file

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using MinecraftClient.Mapping;
namespace MinecraftClient.ChatBots
{
class AutoFishing : ChatBot
{
private Dictionary<int, Entity> fishingRod = new Dictionary<int, Entity>();
private Double fishingHookThreshold = 0.2;
private Location LastPos = new Location();
private DateTime CaughtTime = DateTime.Now;
public override void Initialize()
{
if (!GetEntityHandlingEnabled())
{
ConsoleIO.WriteLine("[AutoFishing] Entity Handling is not enabled in the config file!");
ConsoleIO.WriteLine("Please enable it to use this bot.");
UnloadBot();
}
}
public override void OnEntitySpawn(Entity entity)
{
if (entity.Type == 102)
{
ConsoleIO.WriteLine("Threw a fishing rod");
fishingRod.Add(entity.ID, entity);
LastPos = entity.Location;
}
}
public override void OnEntityMove(Entity entity)
{
if (fishingRod.ContainsKey(entity.ID))
{
Location Pos = entity.Location;
Double Dx = LastPos.X - Pos.X;
Double Dy = LastPos.Y - Pos.Y;
Double Dz = LastPos.Z - Pos.Z;
LastPos = Pos;
// check if fishing hook is stationary
if (Dx == 0 && Dz == 0)
{
if (Math.Abs(Dy) > fishingHookThreshold)
{
// caught
// prevent triggering multiple time
if ((DateTime.Now - CaughtTime).TotalSeconds > 1)
{
OnCaughtFish();
CaughtTime = DateTime.Now;
}
}
}
fishingRod[entity.ID] = entity;
}
}
// TODO: Move into ChatBot
/// <summary>
/// Called when detected a fish is caught
/// </summary>
public void OnCaughtFish()
{
ConsoleIO.WriteLine("Caught a fish!");
// retract fishing rod
UseItemOnHand();
// non-blocking delay
Task.Factory.StartNew(delegate
{
// retract fishing rod need some time
Thread.Sleep(500);
// throw again
// TODO: to check if hand have fishing rod
UseItemOnHand();
});
}
}
}

View file

@ -8,39 +8,35 @@ namespace MinecraftClient.Commands
class AutoAttack : Command class AutoAttack : Command
{ {
public override string CMDName { get { return "autoattack"; } } public override string CMDName { get { return "autoattack"; } }
public override string CMDDesc { get { return "autoattack <on|off>: Enable/disable auto attack mobs."; } } public override string CMDDesc { get { return "autoattack <on|off>: Auto attack mobs around you."; } }
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command)
{ {
if (hasArg(command)) if (hasArg(command))
{ {
string state = getArg(command); string arg = getArg(command);
if (state.ToLower() == "on") if (arg == "on")
{ {
if (!handler.AutoAttack) if (handler.GetEntityHandlingEnabled())
{ {
handler.AutoAttack = true; // TODO: check if the bot already loaded
return "Auto attack turned on."; // I don't know how :C
handler.BotLoad(new ChatBots.AutoAttack());
return "Auto Attack now enabled.";
} }
else else
{ {
return "Auto attack is on."; return "Please enable EntityHandling in the config before using this.";
} }
}else if (state.ToLower() == "off") }
else if(arg == "off")
{ {
if (handler.AutoAttack) // TODO: unload auto attack bot
{ // I don't know how to unload a single bot :C
handler.AutoAttack = false; return "Currently not implemented :/";
return "Auto attack turned off.";
}
else
{
return "Auto attack is off.";
} }
} }
return ""; return CMDDesc;
}
else return CMDDesc;
} }
} }
} }

View file

@ -1,48 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Commands
{
class Fishing : Command
{
public override string CMDName { get { return "fishing"; } }
public override string CMDDesc { get { return "fishing <on|off>: Auto fishing"; } }
public override string Run(McTcpClient handler, string command)
{
if (hasArg(command))
{
string state = getArg(command);
if (state.ToLower() == "on")
{
if (!handler.AutoFishing)
{
handler.AutoFishing = true;
handler.useItemOnHand();
return "Auto fishing turned on.";
}
else
{
return "Auto fishing is on.";
}
}
else if (state.ToLower() == "off")
{
if (handler.AutoFishing)
{
handler.AutoFishing = false;
handler.useItemOnHand();
return "Auto fishing turned off.";
}
else
{
return "Auto fishing is off.";
}
}
}
return CMDDesc;
}
}
}

View file

@ -12,7 +12,7 @@ namespace MinecraftClient.Commands
public override string Run(McTcpClient handler, string command) public override string Run(McTcpClient handler, string command)
{ {
handler.useItemOnHand(); handler.UseItemOnHand();
return "Use an item"; return "Use an item";
} }
} }

View file

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Mapping
{
public class Entity
{
public int ID;
public int Type;
public string Name;
public Location Location;
public Entity(int ID, Location location)
{
this.ID = ID;
this.Location = location;
}
public Entity(int ID, int Type, Location location)
{
this.ID = ID;
this.Type = Type;
this.Name = GetMobName(Type);
this.Location = location;
}
public Entity(int ID, int Type, string Name, Location location)
{
this.ID = ID;
this.Type = Type;
this.Name = Name;
this.Location = location;
}
/// <summary>
/// Calculate the distance between two coordinate
/// </summary>
/// <param name="l1"></param>
/// <param name="l2"></param>
/// <returns></returns>
public static double CalculateDistance(Location l1, Location l2)
{
return Math.Sqrt(Math.Pow(l2.X - l1.X, 2) + Math.Pow(l2.Y - l1.Y, 2) + Math.Pow(l2.Z - l1.Z, 2));
}
/// <summary>
/// Get the mob name by entity type ID.
/// </summary>
/// <param name="EntityType"></param>
/// <returns></returns>
public static string GetMobName(int EntityType)
{
// only mobs in this list will be auto attacked
switch (EntityType)
{
case 5: return "Blaze";
case 12: return "Creeper";
case 16: return "Drowned";
case 23: return "Evoker";
case 29: return "Ghast";
case 31: return "Guardian";
case 33: return "Husk";
case 41: return "Magma Cube";
case 57: return "Zombie Pigman";
case 63: return "Shulker";
case 65: return "Silverfish";
case 66: return "Skeleton";
case 68: return "Slime";
case 75: return "Stray";
case 84: return "Vex";
case 87: return "Vindicator";
case 88: return "Pillager";
case 90: return "Witch";
case 92: return "Wither Skeleton";
case 95: return "Zombie";
case 97: return "Zombie Villager";
case 98: return "Phantom";
case 99: return "Ravager";
default: return "";
}
}
public string GetMobName()
{
return GetMobName(Type);
}
}
}

View file

@ -4,7 +4,6 @@ using System.Linq;
using System.Text; using System.Text;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using System.IO; using System.IO;
using System.Net; using System.Net;
using MinecraftClient.Protocol; using MinecraftClient.Protocol;
@ -36,6 +35,7 @@ namespace MinecraftClient
private bool terrainAndMovementsRequested = false; private bool terrainAndMovementsRequested = false;
private bool inventoryHandlingEnabled; private bool inventoryHandlingEnabled;
private bool inventoryHandlingRequested = false; private bool inventoryHandlingRequested = false;
private bool entityHandlingEnabled;
private object locationLock = new object(); private object locationLock = new object();
private bool locationReceived = false; private bool locationReceived = false;
@ -61,45 +61,14 @@ namespace MinecraftClient
// so I use a Dict instead for player inventory // so I use a Dict instead for player inventory
private Dictionary<int, Item> playerItems; private Dictionary<int, Item> playerItems;
// auto attack // Entity handling
private class Entity private Dictionary<int, Entity> entities = new Dictionary<int, Entity>();
{
public int ID;
public int Type;
public string Name;
public Location Location;
public Entity(int ID, Location location)
{
this.ID = ID;
this.Location = location;
}
public Entity(int ID, int Type, string Name, Location location)
{
this.ID = ID;
this.Type = Type;
this.Name = Name;
this.Location = location;
}
}
private Dictionary<int, Entity> entitiesToAttack = new Dictionary<int, Entity>(); // mobs within attack range
private Dictionary<int, Entity> entitiesToTrack = new Dictionary<int, Entity>(); // all mobs in view distance
private int attackCooldown = 6;
private int attackCooldownCounter = 6;
private Double attackSpeed;
private Double attackCooldownSecond;
private int attackRange = 4;
// server TPS // server TPS
private long lastAge = 0; private long lastAge = 0;
private DateTime lastTime; private DateTime lastTime;
private Double serverTPS = 0; private Double serverTPS = 0;
public bool AutoAttack
{
get => Settings.AutoAttackMobs;
set => Settings.AutoAttackMobs = value;
}
public int GetServerPort() { return port; } public int GetServerPort() { return port; }
public string GetServerHost() { return host; } public string GetServerHost() { return host; }
public string GetUsername() { return username; } public string GetUsername() { return username; }
@ -107,6 +76,13 @@ namespace MinecraftClient
public string GetSessionID() { return sessionid; } public string GetSessionID() { return sessionid; }
public Location GetCurrentLocation() { return location; } public Location GetCurrentLocation() { return location; }
public World GetWorld() { return world; } public World GetWorld() { return world; }
public Double GetServerTPS() { return serverTPS; }
// get bots list for unloading them by commands
public List<ChatBot> GetLoadedChatBots()
{
return bots;
}
TcpClient client; TcpClient client;
IMinecraftCom handler; IMinecraftCom handler;
@ -157,6 +133,7 @@ namespace MinecraftClient
{ {
terrainAndMovementsEnabled = Settings.TerrainAndMovements; terrainAndMovementsEnabled = Settings.TerrainAndMovements;
inventoryHandlingEnabled = Settings.InventoryHandling; inventoryHandlingEnabled = Settings.InventoryHandling;
entityHandlingEnabled = Settings.EntityHandling;
bool retry = false; bool retry = false;
this.sessionid = sessionID; this.sessionid = sessionID;
@ -178,9 +155,10 @@ namespace MinecraftClient
if (Settings.ScriptScheduler_Enabled) { BotLoad(new ChatBots.ScriptScheduler(Settings.ExpandVars(Settings.ScriptScheduler_TasksFile))); } if (Settings.ScriptScheduler_Enabled) { BotLoad(new ChatBots.ScriptScheduler(Settings.ExpandVars(Settings.ScriptScheduler_TasksFile))); }
if (Settings.RemoteCtrl_Enabled) { BotLoad(new ChatBots.RemoteControl()); } if (Settings.RemoteCtrl_Enabled) { BotLoad(new ChatBots.RemoteControl()); }
if (Settings.AutoRespond_Enabled) { BotLoad(new ChatBots.AutoRespond(Settings.AutoRespond_Matches)); } if (Settings.AutoRespond_Enabled) { BotLoad(new ChatBots.AutoRespond(Settings.AutoRespond_Matches)); }
if (Settings.AutoAttack_Enabled) { BotLoad(new ChatBots.AutoAttack()); }
if (Settings.AutoFishing_Enabled) { BotLoad(new ChatBots.AutoFishing()); }
//Add your ChatBot here by uncommenting and adapting //Add your ChatBot here by uncommenting and adapting
//BotLoad(new ChatBots.YourBot()); //BotLoad(new ChatBots.YourBot());
//BotLoad(new ChatBots.kill());
} }
} }
@ -575,6 +553,26 @@ namespace MinecraftClient
return true; return true;
} }
/// <summary>
/// Get entity handling status
/// </summary>
/// <returns></returns>
/// <remarks>Entity Handling cannot be enabled in runtime (or after joining server)</remarks>
public bool GetEntityHandlingEnabled()
{
return entityHandlingEnabled;
}
/// <summary>
/// Get client player's inventory items
/// </summary>
/// <returns> Item Dictionary indexed by Slot ID (Check wiki.vg for slot ID)</returns>
public Dictionary<int, Item> GetPlayerInventory()
{
return playerItems;
}
// TODO: add command for displaying player inventory
/// <summary> /// <summary>
/// Called when the server sends a new player location, /// Called when the server sends a new player location,
/// or if a ChatBot whishes to update the player's location. /// or if a ChatBot whishes to update the player's location.
@ -773,14 +771,9 @@ namespace MinecraftClient
/// <param name="itemList"></param> /// <param name="itemList"></param>
public void OnWindowItems(int type, Dictionary<int, Item> itemList) public void OnWindowItems(int type, Dictionary<int, Item> itemList)
{ {
// player inventory // 0 is player inventory
//if (type == 0) if (type == 0)
// playerItems = itemList; playerItems = itemList;
foreach(KeyValuePair<int,Item> pair in itemList)
{
ConsoleIO.WriteLine("Slot: "+pair.Key+" itemID:"+pair.Value.id);
}
ConsoleIO.WriteLine("Type: "+type);
} }
/// <summary> /// <summary>
@ -880,25 +873,7 @@ namespace MinecraftClient
} }
} }
// auto attack entity within range
if (Settings.AutoAttackMobs)
{
if (attackCooldownCounter == 0)
{
attackCooldownCounter = attackCooldown;
if (entitiesToAttack.Count > 0)
{
foreach (KeyValuePair<int, Entity> a in entitiesToAttack)
{
handler.SendInteractEntityPacket(a.Key, 1);
}
}
}
else
{
attackCooldownCounter--;
}
}
} }
/// <summary> /// <summary>
@ -1102,31 +1077,19 @@ namespace MinecraftClient
} }
} }
private Dictionary<int,Entity> fishingRod = new Dictionary<int, Entity>(); /// <summary>
private Double fishingHookThreshold = -0.3; // must be negetive /// Called when a non-living entity spawned (fishing hook, minecart, etc)
public bool AutoFishing { get; set; } = false; /// </summary>
/// <param name="EntityID"></param>
/// <param name="EntityType"></param>
/// <param name="UUID"></param>
/// <param name="location"></param>
public void OnSpawnEntity(int EntityID, int EntityType, Guid UUID, Location location) public void OnSpawnEntity(int EntityID, int EntityType, Guid UUID, Location location)
{ {
if (EntityType == 102 && AutoFishing) Entity entity = new Entity(EntityID, EntityType, location);
{ entities.Add(EntityID, entity);
ConsoleIO.WriteLine("Threw a fishing rod"); foreach (ChatBot bot in bots.ToArray())
fishingRod.Add(EntityID,new Entity(EntityID, EntityType, "fishing bobber", location)); bot.OnEntitySpawn(entity);
}
}
public void OnEntityStatus(int EntityID, byte EntityStatus)
{
if (fishingRod.ContainsKey(EntityID))
{
if (EntityStatus == 31)
{
ConsoleIO.WriteLine("Status is bobber");
}
else
{
ConsoleIO.WriteLine("Status is " + EntityStatus);
}
}
} }
/// <summary> /// <summary>
@ -1138,19 +1101,10 @@ namespace MinecraftClient
/// <param name="location"></param> /// <param name="location"></param>
public void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location) public void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location)
{ {
string name = getEntityName(EntityType); Entity entity = new Entity(EntityID, EntityType, location);
if (name != "") entities.Add(EntityID, entity);
{ foreach (ChatBot bot in bots.ToArray())
Entity entity = new Entity(EntityID, EntityType, name, location); bot.OnEntitySpawn(entity);
entitiesToTrack.Add(EntityID, entity);
if (Settings.AutoAttackMobs)
{
if (calculateDistance(location, GetCurrentLocation()) < attackRange)
{
entitiesToAttack.Add(EntityID, entity);
}
}
}
} }
/// <summary> /// <summary>
@ -1161,23 +1115,14 @@ namespace MinecraftClient
{ {
foreach (int a in Entities) foreach (int a in Entities)
{ {
if (entitiesToTrack.ContainsKey(a)) if (entities.ContainsKey(a))
{ {
entitiesToAttack.Remove(a); entities.Remove(a);
entitiesToTrack.Remove(a);
} }
foreach (ChatBot bot in bots.ToArray())
if (fishingRod.ContainsKey(a)) bot.OnEntityDespawn(a);
{
fishingRod.Remove(a);
} }
} }
}
public void OnSetCooldown(int itemID, int tick)
{
ConsoleIO.WriteLine("Set Cooldown on item " + itemID + " by " + tick + " ticks");
}
/// <summary> /// <summary>
/// Called when an entity's position changed within 8 block of its previous position. /// Called when an entity's position changed within 8 block of its previous position.
@ -1189,46 +1134,36 @@ namespace MinecraftClient
/// <param name="onGround"></param> /// <param name="onGround"></param>
public void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround) public void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround)
{ {
if (entitiesToTrack.ContainsKey(EntityID)) if (entities.ContainsKey(EntityID))
{ {
Entity entity = entitiesToTrack[EntityID]; Location L = entities[EntityID].Location;
Location L = entity.Location;
L.X += Dx; L.X += Dx;
L.Y += Dy; L.Y += Dy;
L.Z += Dz; L.Z += Dz;
entitiesToTrack[EntityID].Location = L; entities[EntityID].Location = L;
if(entitiesToAttack.ContainsKey(EntityID))
entitiesToAttack[EntityID].Location = L;
Double distance = calculateDistance(L, GetCurrentLocation());
if (distance < attackRange) foreach (ChatBot bot in bots.ToArray())
{ bot.OnEntityMove(new Entity(entities[EntityID].ID, entities[EntityID].Type, entities[EntityID].Location));
if (!entitiesToAttack.ContainsKey(EntityID))
{
entitiesToAttack.Add(EntityID, entity);
} }
} }
else /// <summary>
/// Called when an entity moved over 8 block.
/// </summary>
/// <param name="EntityID"></param>
/// <param name="X"></param>
/// <param name="Y"></param>
/// <param name="Z"></param>
/// <param name="onGround"></param>
public void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround)
{ {
entitiesToAttack.Remove(EntityID); if (entities.ContainsKey(EntityID))
}
}
if (fishingRod.ContainsKey(EntityID))
{ {
Location L = fishingRod[EntityID].Location; Location location = new Location(X, Y, Z);
L.X += Dx; entities[EntityID].Location = location;
L.Y += Dy;
L.Z += Dz; foreach (ChatBot bot in bots.ToArray())
fishingRod[EntityID].Location = L; bot.OnEntityMove(new Entity(entities[EntityID].ID, entities[EntityID].Type, entities[EntityID].Location));
// check if fishing hook is stationary
if (Dx == 0 && Dz == 0)
{
if (Dy < fishingHookThreshold)
{
// caught
OnCaughtFish();
}
}
} }
} }
@ -1241,16 +1176,8 @@ namespace MinecraftClient
{ {
if(EntityID == playerEntityID) if(EntityID == playerEntityID)
{ {
// adjust auto attack cooldown for maximum attack damage foreach (ChatBot bot in bots.ToArray())
if (prop.ContainsKey("generic.attackSpeed")) bot.OnPlayerProperty(prop);
{
if (attackSpeed != prop["generic.attackSpeed"])
{
attackSpeed = prop["generic.attackSpeed"];
attackCooldownSecond = 1 / attackSpeed * (serverTPS / 20.0); // server tps will affect the cooldown
attackCooldown = Convert.ToInt16(Math.Truncate(attackCooldownSecond / 0.1) + 1);
}
}
} }
} }
@ -1261,17 +1188,20 @@ namespace MinecraftClient
/// <param name="TimeOfDay"></param> /// <param name="TimeOfDay"></param>
public void OnTimeUpdate(long WorldAge, long TimeOfDay) public void OnTimeUpdate(long WorldAge, long TimeOfDay)
{ {
if (!Settings.AutoAttackMobs) return; // calculate server tps
// calculate server tps for adjusting attack cooldown
if (lastAge != 0) if (lastAge != 0)
{ {
DateTime currentTime = DateTime.Now; DateTime currentTime = DateTime.Now;
Double tps = (WorldAge - lastAge) / (currentTime - lastTime).TotalSeconds; long tickDiff = WorldAge - lastAge;
Double tps = tickDiff / (currentTime - lastTime).TotalSeconds;
lastAge = WorldAge; lastAge = WorldAge;
lastTime = currentTime; lastTime = currentTime;
if (tps <= 20 || tps >= 0) if (tps <= 20.0 && tps >= 0.0 && serverTPS != tps)
{ {
serverTPS = tps; serverTPS = tps;
// invoke ChatBot
foreach (ChatBot bot in bots.ToArray())
bot.OnServerTpsUpdate(tps);
} }
} }
else else
@ -1282,105 +1212,6 @@ namespace MinecraftClient
} }
/// <summary>
/// Called when an entity moved over 8 block.
/// </summary>
/// <param name="EntityID"></param>
/// <param name="X"></param>
/// <param name="Y"></param>
/// <param name="Z"></param>
/// <param name="onGround"></param>
public void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround)
{
if (Settings.AutoAttackMobs)
{
if (entitiesToTrack.ContainsKey(EntityID))
{
entitiesToTrack[EntityID].Location = new Location(X, Y, Z);
}
}
if (fishingRod.ContainsKey(EntityID))
{
Location L = fishingRod[EntityID].Location;
Double Dy = L.Y - Y;
L.X = X;
L.Y = Y;
L.Z = Z;
fishingRod[EntityID].Location = L;
if (Dy < fishingHookThreshold)
{
// caught
OnCaughtFish();
}
}
}
/// <summary>
/// Called when detected a fish is caught
/// </summary>
public void OnCaughtFish()
{
ConsoleIO.WriteLine("Caught a fish!");
// retract fishing rod
useItemOnHand();
// retract fishing rod need some time
Task.Factory.StartNew(delegate
{
Thread.Sleep(500);
// throw again
// TODO: to check if hand have fishing rod
if(AutoFishing)
useItemOnHand();
});
}
/// <summary>
/// Calculate the distance between two coordinate
/// </summary>
/// <param name="l1"></param>
/// <param name="l2"></param>
/// <returns></returns>
public double calculateDistance(Location l1,Location l2)
{
return Math.Sqrt(Math.Pow(l2.X - l1.X, 2) + Math.Pow(l2.Y - l1.Y, 2) + Math.Pow(l2.Z - l1.Z, 2));
}
/// <summary>
/// Get the entity name by entity type ID.
/// </summary>
/// <param name="EntityType"></param>
/// <returns></returns>
public string getEntityName(int EntityType)
{
// only mobs in this list will be auto attacked
switch (EntityType)
{
case 5: return "Blaze";
case 12: return "Creeper";
case 16: return "Drowned";
case 23: return "Evoker";
case 29: return "Ghast";
case 31: return "Guardian";
case 33: return "Husk";
case 41: return "Magma Cube";
case 57: return "Zombie Pigman";
case 63: return "Shulker";
case 65: return "Silverfish";
case 66: return "Skeleton";
case 68: return "Slime";
case 75: return "Stray";
case 84: return "Vex";
case 87: return "Vindicator";
case 88: return "Pillager";
case 90: return "Witch";
case 92: return "Wither Skeleton";
case 95: return "Zombie";
case 97: return "Zombie Villager";
case 98: return "Phantom";
case 99: return "Ravager";
default: return "";
}
}
/// <summary> /// <summary>
/// Set client player's ID for later receiving player's own properties /// Set client player's ID for later receiving player's own properties
/// </summary> /// </summary>
@ -1390,9 +1221,20 @@ namespace MinecraftClient
playerEntityID = EntityID; playerEntityID = EntityID;
} }
public void useItemOnHand() public bool UseItemOnHand()
{ {
handler.SendUseItemPacket(0); return handler.SendUseItemPacket(0);
}
/// <summary>
/// Interact with an entity
/// </summary>
/// <param name="EntityID"></param>
/// <param name="type">0: interact, 1: attack, 2: interact at</param>
/// <returns></returns>
public bool InteractEntity(int EntityID, int type)
{
return handler.SendInteractEntityPacket(EntityID, type);
} }
} }
} }

View file

@ -75,6 +75,8 @@
<Compile Include="AutoTimeout.cs" /> <Compile Include="AutoTimeout.cs" />
<Compile Include="ChatBots\Alerts.cs" /> <Compile Include="ChatBots\Alerts.cs" />
<Compile Include="ChatBots\AntiAFK.cs" /> <Compile Include="ChatBots\AntiAFK.cs" />
<Compile Include="ChatBots\AutoAttack.cs" />
<Compile Include="ChatBots\AutoFishing.cs" />
<Compile Include="ChatBots\AutoRespond.cs" /> <Compile Include="ChatBots\AutoRespond.cs" />
<Compile Include="ChatBots\AutoRelog.cs" /> <Compile Include="ChatBots\AutoRelog.cs" />
<Compile Include="ChatBots\ChatLog.cs" /> <Compile Include="ChatBots\ChatLog.cs" />
@ -89,7 +91,6 @@
<Compile Include="Commands\AutoAttack.cs" /> <Compile Include="Commands\AutoAttack.cs" />
<Compile Include="Commands\Connect.cs" /> <Compile Include="Commands\Connect.cs" />
<Compile Include="Commands\Debug.cs" /> <Compile Include="Commands\Debug.cs" />
<Compile Include="Commands\Fishing.cs" />
<Compile Include="Commands\Look.cs" /> <Compile Include="Commands\Look.cs" />
<Compile Include="Commands\Move.cs" /> <Compile Include="Commands\Move.cs" />
<Compile Include="Commands\Exit.cs" /> <Compile Include="Commands\Exit.cs" />
@ -106,6 +107,7 @@
<Compile Include="Mapping\BlockPalettes\Palette115.cs" /> <Compile Include="Mapping\BlockPalettes\Palette115.cs" />
<Compile Include="Mapping\BlockPalettes\PaletteGenerator.cs" /> <Compile Include="Mapping\BlockPalettes\PaletteGenerator.cs" />
<Compile Include="Mapping\BlockPalettes\PaletteMapping.cs" /> <Compile Include="Mapping\BlockPalettes\PaletteMapping.cs" />
<Compile Include="Mapping\Entity.cs" />
<Compile Include="Mapping\MaterialExtensions.cs" /> <Compile Include="Mapping\MaterialExtensions.cs" />
<Compile Include="Protocol\Handlers\DataTypes.cs" /> <Compile Include="Protocol\Handlers\DataTypes.cs" />
<Compile Include="Protocol\Handlers\PacketIncomingType.cs" /> <Compile Include="Protocol\Handlers\PacketIncomingType.cs" />

View file

@ -33,7 +33,6 @@ namespace MinecraftClient.Protocol.Handlers
OpenWindow, OpenWindow,
WindowItems, WindowItems,
SetSlot, SetSlot,
UnknownPacket,
DestroyEntities, DestroyEntities,
SetCooldown, SetCooldown,
EntityPosition, EntityPosition,
@ -41,6 +40,7 @@ namespace MinecraftClient.Protocol.Handlers
EntityProperties, EntityProperties,
TimeUpdate, TimeUpdate,
EntityTeleport, EntityTeleport,
EntityStatus EntityStatus,
UnknownPacket
} }
} }

View file

@ -20,7 +20,6 @@ namespace MinecraftClient.Protocol.Handlers
PlayerPosition, PlayerPosition,
PlayerPositionAndLook, PlayerPositionAndLook,
TeleportConfirm, TeleportConfirm,
//modified by reinforce
HeldItemChange, HeldItemChange,
InteractEntity, InteractEntity,
UseItem UseItem

View file

@ -641,6 +641,24 @@ namespace MinecraftClient.Protocol.Handlers
return false; //Currently not implemented return false; //Currently not implemented
} }
//Currently not implemented
public bool SendInteractEntityPacket(int EntityID, int type)
{
return false;
}
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand)
{
return false;
}
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z)
{
return false;
}
public bool SendUseItemPacket(int hand)
{
return false;
}
/// <summary> /// <summary>
/// Send a plugin channel packet to the server. /// Send a plugin channel packet to the server.
/// </summary> /// </summary>
@ -733,23 +751,5 @@ namespace MinecraftClient.Protocol.Handlers
} }
catch { return false; } catch { return false; }
} }
// reinforce
public bool SendInteractEntityPacket(int EntityID, int type)
{
return true;
}
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand)
{
return true;
}
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z)
{
return true;
}
public bool SendUseItemPacket(int hand)
{
return true;
}
} }
} }

View file

@ -245,9 +245,8 @@ namespace MinecraftClient.Protocol.Handlers
float pitch = dataTypes.ReadNextFloat(packetData); float pitch = dataTypes.ReadNextFloat(packetData);
byte locMask = dataTypes.ReadNextByte(packetData); byte locMask = dataTypes.ReadNextByte(packetData);
// player pos is needed for calculate entity distance // entity handling require player pos for distance calculating
// modified by reinforce if (handler.GetTerrainEnabled() || handler.GetEntityHandlingEnabled())
if (handler.GetTerrainEnabled() || true)
{ {
if (protocolversion >= MC18Version) if (protocolversion >= MC18Version)
{ {
@ -510,10 +509,10 @@ namespace MinecraftClient.Protocol.Handlers
} }
break; break;
case PacketIncomingType.WindowItems: case PacketIncomingType.WindowItems:
if (handler.GetInventoryEnabled()||true) if (handler.GetInventoryEnabled()||true) // set true in .ini but GetInventoryEnabled seems like return false
{ {
/* /*
* Following commented code not working * Following commented code will crash
* *
byte id = dataTypes.ReadNextByte(packetData); byte id = dataTypes.ReadNextByte(packetData);
short elements = dataTypes.ReadNextShort(packetData); short elements = dataTypes.ReadNextShort(packetData);
@ -562,6 +561,8 @@ namespace MinecraftClient.Protocol.Handlers
SendPacket(PacketOutgoingType.ResourcePackStatus, dataTypes.ConcatBytes(responseHeader, dataTypes.GetVarInt(0))); //Successfully loaded SendPacket(PacketOutgoingType.ResourcePackStatus, dataTypes.ConcatBytes(responseHeader, dataTypes.GetVarInt(0))); //Successfully loaded
break; break;
case PacketIncomingType.SpawnEntity: case PacketIncomingType.SpawnEntity:
if (handler.GetEntityHandlingEnabled())
{
int EntityID = dataTypes.ReadNextVarInt(packetData); int EntityID = dataTypes.ReadNextVarInt(packetData);
Guid EntityUUID = dataTypes.ReadNextUUID(packetData); Guid EntityUUID = dataTypes.ReadNextUUID(packetData);
int EntityType = dataTypes.ReadNextVarInt(packetData); int EntityType = dataTypes.ReadNextVarInt(packetData);
@ -578,42 +579,46 @@ namespace MinecraftClient.Protocol.Handlers
Location EntityLocation = new Location(X, Y, Z); Location EntityLocation = new Location(X, Y, Z);
handler.OnSpawnEntity(EntityID, EntityType, EntityUUID, EntityLocation); handler.OnSpawnEntity(EntityID, EntityType, EntityUUID, EntityLocation);
}
break; break;
case PacketIncomingType.SpawnLivingEntity: case PacketIncomingType.SpawnLivingEntity:
if (login_phase) break; if (login_phase) break; // same packet ID with login packet
EntityID = dataTypes.ReadNextVarInt(packetData); if (handler.GetEntityHandlingEnabled())
EntityUUID = dataTypes.ReadNextUUID(packetData); {
EntityType = dataTypes.ReadNextVarInt(packetData); int EntityID = dataTypes.ReadNextVarInt(packetData);
X = dataTypes.ReadNextDouble(packetData); Guid EntityUUID = dataTypes.ReadNextUUID(packetData);
Y = dataTypes.ReadNextDouble(packetData); int EntityType = dataTypes.ReadNextVarInt(packetData);
Z = dataTypes.ReadNextDouble(packetData); Double X = dataTypes.ReadNextDouble(packetData);
EntityYaw = dataTypes.ReadNextByte(packetData); Double Y = dataTypes.ReadNextDouble(packetData);
EntityPitch = dataTypes.ReadNextByte(packetData); Double Z = dataTypes.ReadNextDouble(packetData);
byte EntityYaw = dataTypes.ReadNextByte(packetData);
byte EntityPitch = dataTypes.ReadNextByte(packetData);
byte EntityHeadPitch = dataTypes.ReadNextByte(packetData); byte EntityHeadPitch = dataTypes.ReadNextByte(packetData);
VelocityX = dataTypes.ReadNextShort(packetData); short VelocityX = dataTypes.ReadNextShort(packetData);
VelocityY = dataTypes.ReadNextShort(packetData); short VelocityY = dataTypes.ReadNextShort(packetData);
VelocityZ = dataTypes.ReadNextShort(packetData); short VelocityZ = dataTypes.ReadNextShort(packetData);
EntityLocation = new Location(X, Y, Z); Location EntityLocation = new Location(X, Y, Z);
handler.OnSpawnLivingEntity(EntityID,EntityType,EntityUUID,EntityLocation); handler.OnSpawnLivingEntity(EntityID, EntityType, EntityUUID, EntityLocation);
}
break; break;
case PacketIncomingType.DestroyEntities: case PacketIncomingType.DestroyEntities:
if (handler.GetEntityHandlingEnabled())
{
int EntityCount = dataTypes.ReadNextVarInt(packetData); int EntityCount = dataTypes.ReadNextVarInt(packetData);
int[] EntitiesList = new int[EntityCount]; int[] EntitiesList = new int[EntityCount];
for(int i = 0; i < EntityCount; i++) for (int i = 0; i < EntityCount; i++)
{ {
EntitiesList[i] = dataTypes.ReadNextVarInt(packetData); EntitiesList[i] = dataTypes.ReadNextVarInt(packetData);
} }
handler.OnDestroyEntities(EntitiesList); handler.OnDestroyEntities(EntitiesList);
break; }
case PacketIncomingType.SetCooldown:
int _itemID = dataTypes.ReadNextVarInt(packetData);
int tick = dataTypes.ReadNextVarInt(packetData);
handler.OnSetCooldown(_itemID, tick);
break; break;
case PacketIncomingType.EntityPosition: case PacketIncomingType.EntityPosition:
EntityID = dataTypes.ReadNextVarInt(packetData); if (handler.GetEntityHandlingEnabled())
{
int EntityID = dataTypes.ReadNextVarInt(packetData);
Double DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); Double DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData));
Double DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); Double DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData));
Double DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); Double DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData));
@ -621,34 +626,39 @@ namespace MinecraftClient.Protocol.Handlers
DeltaX = DeltaX / (128 * 32); DeltaX = DeltaX / (128 * 32);
DeltaY = DeltaY / (128 * 32); DeltaY = DeltaY / (128 * 32);
DeltaZ = DeltaZ / (128 * 32); DeltaZ = DeltaZ / (128 * 32);
handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ,OnGround); handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ, OnGround);
}
break; break;
case PacketIncomingType.EntityPositionAndRotation: case PacketIncomingType.EntityPositionAndRotation:
EntityID = dataTypes.ReadNextVarInt(packetData); if (handler.GetEntityHandlingEnabled())
DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); {
DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); int EntityID = dataTypes.ReadNextVarInt(packetData);
DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); Double DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData));
yaw = dataTypes.ReadNextByte(packetData); Double DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData));
pitch = dataTypes.ReadNextByte(packetData); Double DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData));
OnGround = dataTypes.ReadNextBool(packetData); byte _yaw = dataTypes.ReadNextByte(packetData);
byte _pitch = dataTypes.ReadNextByte(packetData);
bool OnGround = dataTypes.ReadNextBool(packetData);
DeltaX = DeltaX / (128 * 32); DeltaX = DeltaX / (128 * 32);
DeltaY = DeltaY / (128 * 32); DeltaY = DeltaY / (128 * 32);
DeltaZ = DeltaZ / (128 * 32); DeltaZ = DeltaZ / (128 * 32);
handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ, OnGround); handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ, OnGround);
}
break; break;
case PacketIncomingType.EntityProperties: case PacketIncomingType.EntityProperties:
EntityID = dataTypes.ReadNextVarInt(packetData); if (handler.GetEntityHandlingEnabled())
{
int EntityID = dataTypes.ReadNextVarInt(packetData);
int NumberOfProperties = dataTypes.ReadNextInt(packetData); int NumberOfProperties = dataTypes.ReadNextInt(packetData);
Dictionary<string,Double> keys = new Dictionary<string,Double>(); Dictionary<string, Double> keys = new Dictionary<string, Double>();
for(int i = 0; i < NumberOfProperties; i++) for (int i = 0; i < NumberOfProperties; i++)
{ {
string _key = dataTypes.ReadNextString(packetData); string _key = dataTypes.ReadNextString(packetData);
Double _value = dataTypes.ReadNextDouble(packetData); Double _value = dataTypes.ReadNextDouble(packetData);
int NumberOfModifiers = dataTypes.ReadNextVarInt(packetData); int NumberOfModifiers = dataTypes.ReadNextVarInt(packetData);
//if (NumberOfModifiers == 0) continue; for (int j = 0; j < NumberOfModifiers; j++)
for(int j = 0; j < NumberOfModifiers; j++)
{ {
dataTypes.ReadNextUUID(packetData); dataTypes.ReadNextUUID(packetData);
Double amount = dataTypes.ReadNextDouble(packetData); Double amount = dataTypes.ReadNextDouble(packetData);
@ -663,6 +673,7 @@ namespace MinecraftClient.Protocol.Handlers
keys.Add(_key, _value); keys.Add(_key, _value);
} }
handler.OnEntityProperties(EntityID, keys); handler.OnEntityProperties(EntityID, keys);
}
break; break;
case PacketIncomingType.TimeUpdate: case PacketIncomingType.TimeUpdate:
if (login_phase) break; if (login_phase) break;
@ -671,19 +682,17 @@ namespace MinecraftClient.Protocol.Handlers
handler.OnTimeUpdate(WorldAge, TimeOfday); handler.OnTimeUpdate(WorldAge, TimeOfday);
break; break;
case PacketIncomingType.EntityTeleport: case PacketIncomingType.EntityTeleport:
EntityID = dataTypes.ReadNextVarInt(packetData); if (handler.GetEntityHandlingEnabled())
X = dataTypes.ReadNextDouble(packetData); {
Y = dataTypes.ReadNextDouble(packetData); int EntityID = dataTypes.ReadNextVarInt(packetData);
Z = dataTypes.ReadNextDouble(packetData); Double X = dataTypes.ReadNextDouble(packetData);
EntityYaw = dataTypes.ReadNextByte(packetData); Double Y = dataTypes.ReadNextDouble(packetData);
EntityPitch = dataTypes.ReadNextByte(packetData); Double Z = dataTypes.ReadNextDouble(packetData);
OnGround = dataTypes.ReadNextBool(packetData); byte EntityYaw = dataTypes.ReadNextByte(packetData);
byte EntityPitch = dataTypes.ReadNextByte(packetData);
bool OnGround = dataTypes.ReadNextBool(packetData);
handler.OnEntityTeleport(EntityID, X, Y, Z, OnGround); handler.OnEntityTeleport(EntityID, X, Y, Z, OnGround);
break; }
case PacketIncomingType.EntityStatus:
EntityID = dataTypes.ReadNextInt(packetData);
byte EntityStatus = dataTypes.ReadNextByte(packetData);
handler.OnEntityStatus(EntityID, EntityStatus);
break; break;
default: default:
return false; //Ignored packet return false; //Ignored packet
@ -1195,14 +1204,14 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { return false; } catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; } catch (ObjectDisposedException) { return false; }
} }
// TODO: Interact at block location // TODO: Interact at block location (e.g. chest)
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand) public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand)
{ {
return true; return false;
} }
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z) public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z)
{ {
return true; return false;
} }
public bool SendUseItemPacket(int hand) public bool SendUseItemPacket(int hand)

View file

@ -85,7 +85,6 @@ namespace MinecraftClient.Protocol
/// <returns>True if message was successfully sent</returns> /// <returns>True if message was successfully sent</returns>
bool SendPluginChannelPacket(string channel, byte[] data); bool SendPluginChannelPacket(string channel, byte[] data);
// by reinforce
bool SendInteractEntityPacket(int EntityID, int type); bool SendInteractEntityPacket(int EntityID, int type);
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand); bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand);
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z); bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z);

View file

@ -30,6 +30,7 @@ namespace MinecraftClient.Protocol
bool SetTerrainEnabled(bool enabled); bool SetTerrainEnabled(bool enabled);
bool GetInventoryEnabled(); bool GetInventoryEnabled();
bool SetInventoryEnabled(bool enabled); bool SetInventoryEnabled(bool enabled);
bool GetEntityHandlingEnabled();
/// <summary> /// <summary>
/// Called when a server was successfully joined /// Called when a server was successfully joined
@ -132,8 +133,6 @@ namespace MinecraftClient.Protocol
void OnDestroyEntities(int[] EntityID); void OnDestroyEntities(int[] EntityID);
void OnSetCooldown(int itemID, int tick);
void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround); void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround);
void OnEntityProperties(int EntityID, Dictionary<string, Double> prop); void OnEntityProperties(int EntityID, Dictionary<string, Double> prop);
@ -142,8 +141,6 @@ namespace MinecraftClient.Protocol
void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround); void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround);
void OnEntityStatus(int EntityID, byte EntityStatus);
void OnWindowItems(int type, Dictionary<int, Item> itemList); void OnWindowItems(int type, Dictionary<int, Item> itemList);
void SetPlayerEntityID(int EntityID); void SetPlayerEntityID(int EntityID);

View file

@ -95,7 +95,7 @@ namespace MinecraftClient
public static bool DebugMessages = false; public static bool DebugMessages = false;
public static bool ResolveSrvRecords = true; public static bool ResolveSrvRecords = true;
public static bool ResolveSrvRecordsShortTimeout = true; public static bool ResolveSrvRecordsShortTimeout = true;
public static bool AutoAttackMobs = false; public static bool EntityHandling = false;
//AntiAFK Settings //AntiAFK Settings
public static bool AntiAFK_Enabled = false; public static bool AntiAFK_Enabled = false;
@ -150,12 +150,18 @@ namespace MinecraftClient
public static bool AutoRespond_Enabled = false; public static bool AutoRespond_Enabled = false;
public static string AutoRespond_Matches = "matches.ini"; public static string AutoRespond_Matches = "matches.ini";
//Auto Attack
public static bool AutoAttack_Enabled = false;
//Auto Fishing
public static bool AutoFishing_Enabled = false;
//Custom app variables and Minecraft accounts //Custom app variables and Minecraft accounts
private static readonly Dictionary<string, object> AppVars = new Dictionary<string, object>(); private static readonly Dictionary<string, object> AppVars = new Dictionary<string, object>();
private static readonly Dictionary<string, KeyValuePair<string, string>> Accounts = new Dictionary<string, KeyValuePair<string, string>>(); private static readonly Dictionary<string, KeyValuePair<string, string>> Accounts = new Dictionary<string, KeyValuePair<string, string>>();
private static readonly Dictionary<string, KeyValuePair<string, ushort>> Servers = new Dictionary<string, KeyValuePair<string, ushort>>(); private static readonly Dictionary<string, KeyValuePair<string, ushort>> Servers = new Dictionary<string, KeyValuePair<string, ushort>>();
private enum ParseMode { Default, Main, AppVars, Proxy, MCSettings, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatFormat, AutoRespond }; private enum ParseMode { Default, Main, AppVars, Proxy, MCSettings, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatFormat, AutoRespond, AutoAttack, AutoFishing };
/// <summary> /// <summary>
/// Load settings from the give INI file /// Load settings from the give INI file
@ -196,6 +202,8 @@ namespace MinecraftClient
case "appvars": pMode = ParseMode.AppVars; break; case "appvars": pMode = ParseMode.AppVars; break;
case "autorespond": pMode = ParseMode.AutoRespond; break; case "autorespond": pMode = ParseMode.AutoRespond; break;
case "chatformat": pMode = ParseMode.ChatFormat; break; case "chatformat": pMode = ParseMode.ChatFormat; break;
case "autoattack": pMode = ParseMode.AutoAttack; break;
case "autofishing": pMode = ParseMode.AutoFishing; break;
default: pMode = ParseMode.Default; break; default: pMode = ParseMode.Default; break;
} }
} }
@ -231,7 +239,7 @@ namespace MinecraftClient
case "privatemsgscmdname": PrivateMsgsCmdName = argValue.ToLower().Trim(); break; case "privatemsgscmdname": PrivateMsgsCmdName = argValue.ToLower().Trim(); break;
case "botmessagedelay": botMessageDelay = TimeSpan.FromSeconds(str2int(argValue)); break; case "botmessagedelay": botMessageDelay = TimeSpan.FromSeconds(str2int(argValue)); break;
case "debugmessages": DebugMessages = str2bool(argValue); break; case "debugmessages": DebugMessages = str2bool(argValue); break;
case "autoattackmobs": AutoAttackMobs = str2bool(argValue); break; case "enableentityhandling": EntityHandling = str2bool(argValue); break;
case "botowners": case "botowners":
Bots_Owners.Clear(); Bots_Owners.Clear();
@ -449,6 +457,20 @@ namespace MinecraftClient
} }
break; break;
case ParseMode.AutoAttack:
switch (argName.ToLower())
{
case "enabled": AutoAttack_Enabled = str2bool(argValue); break;
}
break;
case ParseMode.AutoFishing:
switch (argName.ToLower())
{
case "enabled": AutoFishing_Enabled = str2bool(argValue); break;
}
break;
case ParseMode.MCSettings: case ParseMode.MCSettings:
switch (argName.ToLower()) switch (argName.ToLower())
{ {
@ -560,7 +582,7 @@ namespace MinecraftClient
+ "debugmessages=false # Please enable this before submitting bug reports. Thanks!\r\n" + "debugmessages=false # Please enable this before submitting bug reports. Thanks!\r\n"
+ "scriptcache=true # Cache compiled scripts for faster load on low-end devices\r\n" + "scriptcache=true # Cache compiled scripts for faster load on low-end devices\r\n"
+ "timestamps=false # Prepend timestamps to chat messages\r\n" + "timestamps=false # Prepend timestamps to chat messages\r\n"
+ "autoattackmobs=false # Auto attack mobs around client player\r\n" + "enableentityhandling=false # Toggle entities handling\r\n"
+ "\r\n" + "\r\n"
+ "[AppVars]\r\n" + "[AppVars]\r\n"
+ "# yourvar=yourvalue\r\n" + "# yourvar=yourvalue\r\n"
@ -639,7 +661,15 @@ namespace MinecraftClient
+ "\r\n" + "\r\n"
+ "[AutoRespond]\r\n" + "[AutoRespond]\r\n"
+ "enabled=false\r\n" + "enabled=false\r\n"
+ "matchesfile=matches.ini\r\n", Encoding.UTF8); + "matchesfile=matches.ini\r\n"
+ "\r\n"
+ "[AutoAttack]\r\n"
+ "# Entity Handling NEED to be enabled first\r\n"
+ "enabled=false\r\n"
+ "\r\n"
+ "[AutoFishing]\r\n"
+ "# Entity Handling NEED to be enabled first\r\n"
+ "enabled=false", Encoding.UTF8);
} }
/// <summary> /// <summary>