Add code documentation, move and rename a few methods

This commit is contained in:
ORelio 2020-03-28 00:48:41 +01:00
parent 90c6e776e1
commit 195e162c7d
10 changed files with 286 additions and 96 deletions

View file

@ -6,6 +6,9 @@ using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// The AutoAttack bot will automatically attack any hostile mob close to the player
/// </summary>
class AutoAttack : ChatBot
{
private Dictionary<int, Entity> entitiesToAttack = new Dictionary<int, Entity>(); // mobs within attack range
@ -48,7 +51,7 @@ namespace MinecraftClient.ChatBots
public override void OnEntitySpawn(Entity entity)
{
if (entity.GetMobName() != "")
if (entity.IsHostile())
{
entitiesToTrack.Add(entity.ID, entity);
}
@ -64,10 +67,9 @@ namespace MinecraftClient.ChatBots
{
if (entitiesToTrack.ContainsKey(entity.ID))
{
Double distance = Entity.CalculateDistance(GetCurrentLocation(), entity.Location);
if(distance < attackRange)
if (GetCurrentLocation().Distance(entity.Location) < attackRange)
{
if(!entitiesToAttack.ContainsKey(entity.ID))
if (!entitiesToAttack.ContainsKey(entity.ID))
entitiesToAttack.Add(entity.ID, entity);
}
}

View file

@ -8,6 +8,10 @@ using MinecraftClient.Mapping;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// The AutoFishing bot semi-automates fishing.
/// The player needs to have a fishing rod in hand, then manually send it using the UseItem command.
/// </summary>
class AutoFishing : ChatBot
{
private Entity fishingRod;
@ -32,7 +36,7 @@ namespace MinecraftClient.ChatBots
{
if (entity.TypeID == 102)
{
if (Entity.CalculateDistance(GetCurrentLocation(), entity.Location) < 2 && !isFishing)
if (GetCurrentLocation().Distance(entity.Location) < 2 && !isFishing)
{
ConsoleIO.WriteLine("Threw a fishing rod");
fishingRod = entity;
@ -41,6 +45,7 @@ namespace MinecraftClient.ChatBots
}
}
}
public override void OnEntityDespawn(Entity entity)
{
if(entity.TypeID == 102)
@ -51,6 +56,7 @@ namespace MinecraftClient.ChatBots
}
}
}
public override void OnEntityMove(Entity entity)
{
if (isFishing)
@ -107,9 +113,14 @@ namespace MinecraftClient.ChatBots
});
}
/// <summary>
/// Check whether the player has a fishing rod in inventory
/// </summary>
/// <returns>TRUE if the player has a fishing rod</returns>
public bool hasFishingRod()
{
if (!inventoryEnabled) return false;
if (!inventoryEnabled)
return false;
int start = 36;
int end = 44;
Inventory.Container container = GetPlayerInventory();

View file

@ -5,97 +5,117 @@ using System.Text;
namespace MinecraftClient.Mapping
{
/// <summary>
/// Represents an entity evolving into a Minecraft world
/// </summary>
public class Entity
{
/// <summary>
/// ID of the entity on the Minecraft server
/// </summary>
public int ID;
public int TypeID;
/// <summary>
/// Entity type determined by Minecraft Console Client
/// </summary>
public EntityType Type;
public string Name;
/// <summary>
/// Entity type ID (more precise than Type, but may change between Minecraft versions)
/// </summary>
public int TypeID;
/// <summary>
/// Entity location in the Minecraft world
/// </summary>
public Location Location;
/// <summary>
/// Create a new entity based on Entity ID and location
/// </summary>
/// <param name="ID">Entity ID</param>
/// <param name="location">Entity location</param>
public Entity(int ID, Location location)
{
this.ID = ID;
this.Location = location;
}
/// <summary>
/// Create a new entity based on Entity ID, Entity Type and location
/// </summary>
/// <param name="ID">Entity ID</param>
/// <param name="TypeID">Entity Type ID</param>
/// <param name="location">Entity location</param>
public Entity(int ID, int TypeID, Location location)
{
this.ID = ID;
this.TypeID = TypeID;
this.Name = GetMobName(TypeID);
this.Location = location;
}
/// <summary>
/// Create a new entity based on Entity ID, Entity Type and location
/// </summary>
/// <param name="ID">Entity ID</param>
/// <param name="TypeID">Entity Type ID</param>
/// <param name="type">Entity Type Enum</param>
/// <param name="location">Entity location</param>
public Entity(int ID, int TypeID, EntityType type, Location location)
{
this.ID = ID;
this.TypeID = TypeID;
this.Type = type;
this.Name = GetMobName(TypeID);
this.Location = location;
}
/// <summary>
/// Create a new entity based on Entity ID, Entity Type and location
/// </summary>
/// <param name="ID">Entity ID</param>
/// <param name="type">Entity Type Enum</param>
/// <param name="location">Entity location</param>
public Entity(int ID, EntityType type, Location location)
{
this.ID = ID;
this.Type = type;
this.Location = location;
}
public Entity(int ID, int TypeID, string Name, Location location)
{
this.ID = ID;
this.TypeID = TypeID;
this.Name = Name;
this.Location = location;
}
/// <summary>
/// Calculate the distance between two coordinate
/// Return TRUE if the Entity is an hostile mob
/// </summary>
/// <param name="l1"></param>
/// <param name="l2"></param>
/// <returns></returns>
public static double CalculateDistance(Location l1, Location l2)
/// <remarks>New mobs added in newer Minecraft versions might be absent from the list</remarks>
/// <returns>TRUE if hostile</returns>
public bool IsHostile()
{
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)
switch (TypeID)
{
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 "";
case 5: return true; // Blaze;
case 12: return true; // Creeper
case 16: return true; // Drowned
case 23: return true; // Evoker
case 29: return true; // Ghast
case 31: return true; // Guardian
case 33: return true; // Husk
case 41: return true; // Magma Cube
case 57: return true; // Zombie Pigman
case 63: return true; // Shulker
case 65: return true; // Silverfish
case 66: return true; // Skeleton
case 68: return true; // Slime
case 75: return true; // Stray
case 84: return true; // Vex
case 87: return true; // Vindicator
case 88: return true; // Pillager
case 90: return true; // Witch
case 92: return true; // Wither Skeleton
case 95: return true; // Zombie
case 97: return true; // Zombie Villager
case 98: return true; // Phantom
case 99: return true; // Ravager
default: return false;
}
}
public string GetMobName()
{
return GetMobName(TypeID);
}
}
}

View file

@ -565,6 +565,12 @@ namespace MinecraftClient
return entityHandlingEnabled;
}
/// <summary>
/// Enable or disable Entity handling.
/// Please note that Enabling will be deferred until next relog.
/// </summary>
/// <param name="enabled">Enabled</param>
/// <returns>TRUE if the setting was applied immediately, FALSE if delayed.</returns>
public bool SetEntityHandlingEnabled(bool enabled)
{
if (!enabled)
@ -594,7 +600,6 @@ namespace MinecraftClient
{
return playerInventory;
}
// TODO: add command for displaying player inventory
/// <summary>
/// Called when the server sends a new player location,
@ -791,8 +796,8 @@ namespace MinecraftClient
/// <summary>
/// When received window items from server.
/// </summary>
/// <param name="type"></param>
/// <param name="itemList"></param>
/// <param name="type">Inventory type</param>
/// <param name="itemList">Item list</param>
public void OnWindowItems(int type, Dictionary<int, Inventory.Item> itemList)
{
// 0 is player inventory
@ -800,15 +805,28 @@ namespace MinecraftClient
playerInventory.Items = itemList;
}
public void OnSetSlot(byte WindowID, short SlotID, bool Present)
/// <summary>
/// When a slot is cleared inside window items
/// </summary>
/// <param name="WindowID">Window ID</param>
/// <param name="SlotID">Slot ID</param>
public void OnSlotClear(byte WindowID, short SlotID)
{
if(WindowID == 0)
if (WindowID == 0 && playerInventory.Items.ContainsKey(SlotID))
{
if (playerInventory.Items.ContainsKey(SlotID))
playerInventory.Items.Remove(SlotID);
playerInventory.Items.Remove(SlotID);
}
}
public void OnSetSlot(byte WindowID, short SlotID, bool Present, int ItemID, byte Count, Dictionary<string, object> NBT)
/// <summary>
/// When a slot is set inside window items
/// </summary>
/// <param name="WindowID">Window ID</param>
/// <param name="SlotID">Slot ID</param>
/// <param name="ItemID">Item ID</param>
/// <param name="Count">Item Count</param>
/// <param name="NBT">Item Metadata</param>
public void OnSetSlot(byte WindowID, short SlotID, int ItemID, byte Count, Dictionary<string, object> NBT)
{
if (WindowID == 0)
{
@ -912,8 +930,6 @@ namespace MinecraftClient
pitch = null;
}
}
}
/// <summary>
@ -1275,12 +1291,16 @@ namespace MinecraftClient
/// <summary>
/// Set client player's ID for later receiving player's own properties
/// </summary>
/// <param name="EntityID"></param>
/// <param name="EntityID">Player Entity ID</param>
public void SetPlayerEntityID(int EntityID)
{
playerEntityID = EntityID;
}
/// <summary>
/// Use the item currently in the player's hand
/// </summary>
/// <returns>TRUE if the item was successfully used</returns>
public bool UseItemOnHand()
{
return handler.SendUseItemPacket(0);
@ -1296,13 +1316,24 @@ namespace MinecraftClient
{
return handler.SendInteractEntityPacket(EntityID, type);
}
// not work :(
/// <summary>
/// Place the block at hand in the Minecraft world
/// </summary>
/// <param name="location">Location to place block to</param>
/// <returns>TRUE if successfully placed</returns>
public bool PlaceBlock(Location location)
{
//WORK IN PROGRESS. MAY NOT WORK YET
ConsoleIO.WriteLine(location.ToString());
return handler.SendPlayerBlockPlacement(0, location, 1, 0.5f, 0.5f, 0.5f, false);
}
/// <summary>
/// Change active slot in the player inventory
/// </summary>
/// <param name="slot">Slot to activate (0 to 8)</param>
/// <returns></returns>
public bool ChangeSlot(short slot)
{
if (slot >= 0 && slot <= 8)

View file

@ -641,30 +641,34 @@ namespace MinecraftClient.Protocol.Handlers
return false; //Currently not implemented
}
//Currently not implemented
public bool SendInteractEntityPacket(int EntityID, int type)
{
return false;
return false; //Currently not implemented
}
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand)
{
return false;
return false; //Currently not implemented
}
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z)
{
return false;
return false; //Currently not implemented
}
public bool SendUseItemPacket(int hand)
{
return false;
return false; //Currently not implemented
}
public bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock)
{
return false;
return false; //Currently not implemented
}
public bool SendHeldItemChange(short slot)
{
return false;
return false; //Currently not implemented
}
/// <summary>
@ -672,7 +676,6 @@ namespace MinecraftClient.Protocol.Handlers
/// </summary>
/// <param name="channel">Channel to send packet on</param>
/// <param name="data">packet Data</param>
public bool SendPluginChannelPacket(string channel, byte[] data)
{
try {

View file

@ -589,7 +589,7 @@ namespace MinecraftClient.Protocol.Handlers
short ItemID = dataTypes.ReadNextShort(packetData);
if (ItemID == -1)
{
handler.OnSetSlot(WindowID, SlotID, false);
handler.OnSlotClear(WindowID, SlotID);
}
else
{
@ -601,7 +601,7 @@ namespace MinecraftClient.Protocol.Handlers
{
NBT = dataTypes.ReadNextNbt(packetData);
}
handler.OnSetSlot(WindowID, SlotID, true, ItemID, Count, NBT);
handler.OnSetSlot(WindowID, SlotID, ItemID, Count, NBT);
}
}
else
@ -615,11 +615,11 @@ namespace MinecraftClient.Protocol.Handlers
int ItemID = dataTypes.ReadNextVarInt(packetData);
byte Count = dataTypes.ReadNextByte(packetData);
Dictionary<string, object> NBT = dataTypes.ReadNextNbt(packetData);
handler.OnSetSlot(WindowID, SlotID, Present, ItemID, Count, NBT);
handler.OnSetSlot(WindowID, SlotID, ItemID, Count, NBT);
}
else
{
handler.OnSetSlot(WindowID, SlotID, Present);
handler.OnSlotClear(WindowID, SlotID);
}
}
}

View file

@ -85,14 +85,62 @@ namespace MinecraftClient.Protocol
/// <returns>True if message was successfully sent</returns>
bool SendPluginChannelPacket(string channel, byte[] data);
/// <summary>
/// Send a held item change packet to the server.
/// </summary>
/// <param name="slot">New active slot in the inventory hotbar</param>
/// <returns>True if packet was successfully sent</returns>
bool SendHeldItemChange(short slot);
/// <summary>
/// Send an entity interaction packet to the server.
/// </summary>
/// <param name="EntityID">Entity ID to interact with</param>
/// <param name="type">Type of interaction (0: interact, 1: attack, 2: interact at)</param>
/// <returns>True if packet was successfully sent</returns>
bool SendInteractEntityPacket(int EntityID, int type);
/// <summary>
/// Send an entity interaction packet to the server.
/// </summary>
/// <param name="EntityID">Entity ID to interact with</param>
/// <param name="type">Type of interaction (0: interact, 1: attack, 2: interact at)</param>
/// <param name="X">X coordinate for "interact at"</param>
/// <param name="Y">Y coordinate for "interact at"</param>
/// <param name="Z">Z coordinate for "interact at"</param>
/// <param name="hand">Player hand (0: main hand, 1: off hand)</param>
/// <returns>True if packet was successfully sent</returns>
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand);
/// <summary>
/// Send an entity interaction packet to the server.
/// </summary>
/// <param name="EntityID">Entity ID to interact with</param>
/// <param name="type">Type of interaction (0: interact, 1: attack, 2: interact at)</param>
/// <param name="X">X coordinate for "interact at"</param>
/// <param name="Y">Y coordinate for "interact at"</param>
/// <param name="Z">Z coordinate for "interact at"</param>
/// <returns>True if packet was successfully sent</returns>
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z);
/// <summary>
/// Send a use item packet to the server
/// </summary>
/// <param name="hand">0: main hand, 1: off hand</param>
/// <returns>True if packet was successfully sent</returns>
bool SendUseItemPacket(int hand);
/// <summary>
/// Send player block placement packet to the server
/// </summary>
/// <param name="hand">0: main hand, 1: off hand</param>
/// <param name="location">Location to place block at</param>
/// <param name="face">Block face</param>
/// <param name="CursorX">Cursor X</param>
/// <param name="CursorY">Cursor Y</param>
/// <param name="CursorZ">Cursor Z</param>
/// <param name="insideBlock">TRUE if inside block</param>
/// <returns>True if packet was successfully sent</returns>
bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock);
}
}

View file

@ -128,27 +128,102 @@ namespace MinecraftClient.Protocol
/// <param name="data">The data from the channel</param>
void OnPluginChannelMessage(string channel, byte[] data);
/// <summary>
/// Called when a non-living entity has spawned
/// </summary>
/// <param name="EntityID">Entity ID</param>
/// <param name="EntityType">Entity Type ID</param>
/// <param name="UUID">Entity UUID</param>
/// <param name="location">Entity location</param>
void OnSpawnEntity(int EntityID, int EntityType, Guid UUID, Location location);
/// <summary>
/// Called when a living entity has spawned
/// </summary>
/// <param name="EntityID">Entity ID</param>
/// <param name="EntityType">Entity Type ID</param>
/// <param name="UUID">Entity UUID</param>
/// <param name="location">Entity location</param>
void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location);
/// <summary>
/// Called when a player has spawned
/// </summary>
/// <param name="EntityID">Entity ID</param>
/// <param name="UUID">Entity UUID</param>
/// <param name="location">Entity location</param>
/// <param name="Yaw">Player head yaw</param>
/// <param name="Pitch">Player head pitch</param>
void OnSpawnPlayer(int EntityID, Guid UUID, Location location, byte Yaw, byte Pitch);
/// <summary>
/// Called when entities have despawned
/// </summary>
/// <param name="EntityID">List of Entity ID that have despawned</param>
void OnDestroyEntities(int[] EntityID);
/// <summary>
/// Called when an entity moved by coordinate offset
/// </summary>
/// <param name="EntityID">Entity ID</param>
/// <param name="Dx">X offset</param>
/// <param name="Dy">Y offset</param>
/// <param name="Dz">Z offset</param>
/// <param name="onGround">TRUE if on ground</param>
void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround);
void OnEntityProperties(int EntityID, Dictionary<string, Double> prop);
void OnTimeUpdate(long WorldAge, long TimeOfDay);
/// <summary>
/// Called when an entity moved to fixed coordinates
/// </summary>
/// <param name="EntityID">Entity ID</param>
/// <param name="Dx">X</param>
/// <param name="Dy">Y</param>
/// <param name="Dz">Z</param>
/// <param name="onGround">TRUE if on ground</param>
void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround);
/// <summary>
/// Called when additional properties have been received for an entity
/// </summary>
/// <param name="EntityID">Entity ID</param>
/// <param name="prop">Dictionary of properties</param>
void OnEntityProperties(int EntityID, Dictionary<string, Double> prop);
/// <summary>
/// Called when the world age has been updated
/// </summary>
/// <param name="WorldAge">World age</param>
/// <param name="TimeOfDay">Time of Day</param>
void OnTimeUpdate(long WorldAge, long TimeOfDay);
/// <summary>
/// Called when inventory items have been received
/// </summary>
/// <param name="type">Inventory type</param>
/// <param name="itemList">Item list</param>
void OnWindowItems(int type, Dictionary<int, MinecraftClient.Inventory.Item> itemList);
void OnSetSlot(byte WindowID, short SlotID, bool Present);
void OnSetSlot(byte WindowID, short SlotID, bool Present, int ItemID, byte Count, Dictionary<string, object> NBT);
/// <summary>
/// Called when a single slot has been cleared inside an inventory
/// </summary>
/// <param name="WindowID">Inventory ID</param>
/// <param name="SlotID">Slot ID</param>
void OnSlotClear(byte WindowID, short SlotID);
/// <summary>
/// Called when a single slot has been updated inside an inventory
/// </summary>
/// <param name="WindowID">Inventory ID</param>
/// <param name="SlotID">Slot ID</param>
/// <param name="ItemID">Item ID</param>
/// <param name="Count">Item Count</param>
/// <param name="NBT">Item Metadata</param>
void OnSetSlot(byte WindowID, short SlotID, int ItemID, byte Count, Dictionary<string, object> NBT);
/// <summary>
/// Called when the Player entity ID has been received from the server
/// </summary>
/// <param name="EntityID">Player entity ID</param>
void SetPlayerEntityID(int EntityID);
}
}

View file

@ -261,7 +261,7 @@ Also, remember that when you connect to a server with this program, you will app
This means that **you can die if you log in in an unsafe place on a survival server!**
Use the script scheduler bot to send a teleport command after logging in.
You have been reminded that **you may get banned** by your server for using this program. Use accordinly with server rules.
We remind you that **you may get banned** by your server for using this program. Use accordingly with server rules.
License
------

View file

@ -32,15 +32,15 @@ Edit `MinecraftClient.csproj` to set the Build target to `Release` on [line 4](h
### On Windows
1. Locate MSBuild.exe for .NET 4 inside `C:\Windows\Microsoft.NET\Framework\v4.X.XXXXX`
1. Locate `MSBuild.exe` for .NET 4 inside `C:\Windows\Microsoft.NET\Framework\v4.X.XXXXX`
2. Drag and drop `MinecraftClient.csproj` over `MSBuild.exe` to launch the build
3. If the build succeededs, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release`
3. If the build succeeds, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release`
### On Mac and Linux
1. Install the [Mono Framework](https://www.mono-project.com/download/stable/#download-lin) if not already installed
2. Run `msbuild MinecraftClient.csproj` in a terminal
3. If the build succeededs, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release`
3. If the build succeeds, you can find `MinecraftClient.exe` under `MinecraftClient\bin\Release`
## How to contribute