mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Finish AutoCraft core functional part
This commit is contained in:
parent
82fb081828
commit
97d7325939
5 changed files with 220 additions and 52 deletions
|
|
@ -1181,6 +1181,16 @@ namespace MinecraftClient
|
||||||
return Handler.RegisterCommand(cmdName, cmdDesc, callback);
|
return Handler.RegisterCommand(cmdName, cmdDesc, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Close a opened inventory
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inventoryID"></param>
|
||||||
|
/// <returns>True if success</returns>
|
||||||
|
protected bool CloseInventory(int inventoryID)
|
||||||
|
{
|
||||||
|
return Handler.CloseInventory(inventoryID);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Command runner definition.
|
/// Command runner definition.
|
||||||
/// Returned string will be the output of the command
|
/// Returned string will be the output of the command
|
||||||
|
|
|
||||||
|
|
@ -9,21 +9,86 @@ namespace MinecraftClient.ChatBots
|
||||||
{
|
{
|
||||||
class AutoCarft : ChatBot
|
class AutoCarft : ChatBot
|
||||||
{
|
{
|
||||||
private bool waitingForResult = false;
|
private bool waitingForUpdate = false;
|
||||||
private int inventoryInUse;
|
private int inventoryInUse = -2;
|
||||||
|
private int index = 0;
|
||||||
|
private Recipe recipeInUse;
|
||||||
|
|
||||||
|
private int updateDebounce = 0;
|
||||||
|
|
||||||
|
private bool craftingFailed = false;
|
||||||
|
|
||||||
private enum ActionType
|
private enum ActionType
|
||||||
{
|
{
|
||||||
MoveTo,
|
LeftClick,
|
||||||
|
ShiftClick,
|
||||||
WaitForUpdate,
|
WaitForUpdate,
|
||||||
|
ResetCraftArea,
|
||||||
Repeat
|
Repeat
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ActionStep
|
private class ActionStep
|
||||||
{
|
{
|
||||||
public ActionType Action;
|
public ActionType ActionType;
|
||||||
public int Slot;
|
public int Slot = -2;
|
||||||
public int InventoryID;
|
public int InventoryID = -2;
|
||||||
|
public ItemType ItemType;
|
||||||
|
|
||||||
|
public ActionStep(ActionType actionType)
|
||||||
|
{
|
||||||
|
ActionType = actionType;
|
||||||
|
}
|
||||||
|
public ActionStep(ActionType actionType, int inventoryID)
|
||||||
|
{
|
||||||
|
ActionType = actionType;
|
||||||
|
InventoryID = inventoryID;
|
||||||
|
}
|
||||||
|
public ActionStep(ActionType actionType, int inventoryID, int slot)
|
||||||
|
{
|
||||||
|
ActionType = actionType;
|
||||||
|
Slot = slot;
|
||||||
|
InventoryID = inventoryID;
|
||||||
|
}
|
||||||
|
public ActionStep(ActionType actionType, int inventoryID, ItemType itemType)
|
||||||
|
{
|
||||||
|
ActionType = actionType;
|
||||||
|
InventoryID = inventoryID;
|
||||||
|
ItemType = itemType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ActionStep> actionSteps = new List<ActionStep>();
|
||||||
|
|
||||||
|
private class Recipe
|
||||||
|
{
|
||||||
|
public ItemType ResultItem;
|
||||||
|
public ContainerType CraftingAreaType;
|
||||||
|
public Dictionary<int, ItemType> Materials;
|
||||||
|
|
||||||
|
public Recipe(Dictionary<int, ItemType> materials, ItemType resultItem, ContainerType type)
|
||||||
|
{
|
||||||
|
Materials = materials;
|
||||||
|
ResultItem = resultItem;
|
||||||
|
CraftingAreaType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Recipe ConvertToCraftingTable(Recipe recipe)
|
||||||
|
{
|
||||||
|
if (recipe.CraftingAreaType == ContainerType.PlayerInventory)
|
||||||
|
{
|
||||||
|
if (recipe.Materials.ContainsKey(4))
|
||||||
|
{
|
||||||
|
recipe.Materials[5] = recipe.Materials[4];
|
||||||
|
recipe.Materials.Remove(4);
|
||||||
|
}
|
||||||
|
if (recipe.Materials.ContainsKey(3))
|
||||||
|
{
|
||||||
|
recipe.Materials[4] = recipe.Materials[3];
|
||||||
|
recipe.Materials.Remove(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return recipe;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
|
|
@ -55,64 +120,134 @@ namespace MinecraftClient.ChatBots
|
||||||
|
|
||||||
public string CraftCommand(string command, string[] args)
|
public string CraftCommand(string command, string[] args)
|
||||||
{
|
{
|
||||||
Dictionary<int, ItemType> recipe = new Dictionary<int, ItemType>
|
Dictionary<int, ItemType> materials = new Dictionary<int, ItemType>
|
||||||
{
|
{
|
||||||
{ 1, ItemType.Stone }
|
{ 1, ItemType.Coal },
|
||||||
|
{ 3, ItemType.Stick }
|
||||||
};
|
};
|
||||||
var inventory = GetInventories()[0];
|
Recipe recipe = new Recipe(materials, ItemType.StoneButton, ContainerType.PlayerInventory);
|
||||||
int slotToPut = -2;
|
|
||||||
int slotToTake = -2;
|
|
||||||
inventoryInUse = 0;
|
inventoryInUse = 0;
|
||||||
foreach (KeyValuePair<int, ItemType> slot in recipe)
|
|
||||||
|
recipeInUse = recipe;
|
||||||
|
craftingFailed = false;
|
||||||
|
waitingForUpdate = false;
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
var inventory = GetInventories()[inventoryInUse];
|
||||||
|
foreach (KeyValuePair<int, ItemType> slot in recipe.Materials)
|
||||||
{
|
{
|
||||||
slotToPut = slot.Key + 1;
|
actionSteps.Add(new ActionStep(ActionType.LeftClick, inventoryInUse, slot.Value));
|
||||||
slotToTake = -2;
|
actionSteps.Add(new ActionStep(ActionType.LeftClick, inventoryInUse, slot.Key));
|
||||||
// Find material in our inventory
|
|
||||||
foreach (KeyValuePair<int, Item> item in inventory.Items)
|
|
||||||
{
|
|
||||||
if (slot.Value == item.Value.Type)
|
|
||||||
{
|
|
||||||
slotToTake = item.Key;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (slotToTake != -2)
|
|
||||||
{
|
|
||||||
// move found material to correct crafting slot
|
|
||||||
WindowAction(0, slotToTake, WindowActionType.LeftClick);
|
|
||||||
WindowAction(0, slotToPut, WindowActionType.LeftClick);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (slotToPut != -2 && slotToTake != -2)
|
if (actionSteps.Count > 0)
|
||||||
{
|
{
|
||||||
waitingForResult = true;
|
actionSteps.Add(new ActionStep(ActionType.WaitForUpdate, inventoryInUse, 0));
|
||||||
// Now wait for server to update the slot 0, craft result
|
actionSteps.Add(new ActionStep(ActionType.ShiftClick, inventoryInUse, 0));
|
||||||
return "Waiting for result";
|
actionSteps.Add(new ActionStep(ActionType.WaitForUpdate, inventoryInUse));
|
||||||
|
actionSteps.Add(new ActionStep(ActionType.Repeat));
|
||||||
|
HandleNextStep();
|
||||||
|
return "AutoCraft start!";
|
||||||
}
|
}
|
||||||
else return "Failed before waiting for result";
|
else return "AutoCraft cannot be started. Check your available materials";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInventoryUpdate(int inventoryId)
|
public override void OnInventoryUpdate(int inventoryId)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine("Inventory " + inventoryId + " is being updated");
|
if (waitingForUpdate && inventoryInUse == inventoryId)
|
||||||
if (waitingForResult && inventoryInUse == inventoryId)
|
|
||||||
{
|
{
|
||||||
var inventory = GetInventories()[inventoryId];
|
updateDebounce = 2;
|
||||||
if (inventory.Items.ContainsKey(0))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if (updateDebounce > 0)
|
||||||
|
{
|
||||||
|
updateDebounce--;
|
||||||
|
if (updateDebounce <= 0)
|
||||||
|
InventoryUpdateFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InventoryUpdateFinished()
|
||||||
|
{
|
||||||
|
waitingForUpdate = false;
|
||||||
|
HandleNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleNextStep()
|
||||||
|
{
|
||||||
|
while (actionSteps.Count > 0)
|
||||||
|
{
|
||||||
|
if (waitingForUpdate) break;
|
||||||
|
ActionStep step = actionSteps[index];
|
||||||
|
index++;
|
||||||
|
switch (step.ActionType)
|
||||||
{
|
{
|
||||||
// slot 0 have item, click on it
|
case ActionType.LeftClick:
|
||||||
WindowAction(0, 0, WindowActionType.LeftClick);
|
if (step.Slot != -2)
|
||||||
// Now wait for server to update our inventory
|
{
|
||||||
ConsoleIO.WriteLine("Crafting success");
|
WindowAction(step.InventoryID, step.Slot, WindowActionType.LeftClick);
|
||||||
}
|
}
|
||||||
else if (inventory.Items.ContainsKey(-1))
|
else
|
||||||
{
|
{
|
||||||
// Server have updated our cursor to the item we want to take out from craft result
|
int[] slots = GetInventories()[step.InventoryID].SearchItem(step.ItemType);
|
||||||
// Now put the item back to our inventory
|
if (slots.Count() > 0)
|
||||||
WindowAction(0, 37, WindowActionType.LeftClick);
|
{
|
||||||
ConsoleIO.WriteLine("Moved crafted item to inventory");
|
int ignoredSlot;
|
||||||
waitingForResult = false;
|
if (recipeInUse.CraftingAreaType == ContainerType.PlayerInventory)
|
||||||
|
ignoredSlot = 9;
|
||||||
|
else
|
||||||
|
ignoredSlot = 10;
|
||||||
|
slots = slots.Where(slot => slot >= ignoredSlot).ToArray();
|
||||||
|
if (slots.Count() > 0)
|
||||||
|
WindowAction(step.InventoryID, slots[0], WindowActionType.LeftClick);
|
||||||
|
else
|
||||||
|
craftingFailed = true;
|
||||||
|
}
|
||||||
|
else craftingFailed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActionType.ShiftClick:
|
||||||
|
if (step.Slot == 0)
|
||||||
|
{
|
||||||
|
WindowAction(step.InventoryID, step.Slot, WindowActionType.ShiftClick);
|
||||||
|
}
|
||||||
|
else craftingFailed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActionType.WaitForUpdate:
|
||||||
|
if (step.InventoryID != -2)
|
||||||
|
{
|
||||||
|
waitingForUpdate = true;
|
||||||
|
}
|
||||||
|
else craftingFailed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActionType.ResetCraftArea:
|
||||||
|
if (step.InventoryID != -2)
|
||||||
|
CloseInventory(step.InventoryID);
|
||||||
|
else
|
||||||
|
craftingFailed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActionType.Repeat:
|
||||||
|
index = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
HandleError();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleError()
|
||||||
|
{
|
||||||
|
if (craftingFailed)
|
||||||
|
{
|
||||||
|
actionSteps.Clear();
|
||||||
|
CloseInventory(inventoryInUse);
|
||||||
|
ConsoleIO.WriteLogLine("Crafting aborted! Check your available materials.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,5 +153,24 @@ namespace MinecraftClient.Inventory
|
||||||
default: return ContainerType.Unknown;
|
default: return ContainerType.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search an item in the container
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemType">The item to search</param>
|
||||||
|
/// <returns>An array of slot ID</returns>
|
||||||
|
public int[] SearchItem(ItemType itemType)
|
||||||
|
{
|
||||||
|
List<int> result = new List<int>();
|
||||||
|
if (Items != null)
|
||||||
|
{
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
if (item.Value.Type == itemType)
|
||||||
|
result.Add(item.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1113,6 +1113,7 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WindowActionType.ShiftClick:
|
case WindowActionType.ShiftClick:
|
||||||
|
if (slotId == 0) break;
|
||||||
if (inventory.Items.ContainsKey(slotId))
|
if (inventory.Items.ContainsKey(slotId))
|
||||||
{
|
{
|
||||||
/* Target slot have item */
|
/* Target slot have item */
|
||||||
|
|
@ -1192,11 +1193,13 @@ namespace MinecraftClient
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="windowId">Window ID</param>
|
/// <param name="windowId">Window ID</param>
|
||||||
/// <returns>TRUE if the window was successfully closed</returns>
|
/// <returns>TRUE if the window was successfully closed</returns>
|
||||||
|
/// <remarks>Sending close window for inventory 0 can cause server to update our inventory if there are any item in the crafting area</remarks>
|
||||||
public bool CloseInventory(int windowId)
|
public bool CloseInventory(int windowId)
|
||||||
{
|
{
|
||||||
if (windowId != 0 && inventories.ContainsKey(windowId))
|
if (inventories.ContainsKey(windowId))
|
||||||
{
|
{
|
||||||
inventories.Remove(windowId);
|
if (windowId != 0)
|
||||||
|
inventories.Remove(windowId);
|
||||||
return handler.SendCloseWindow(windowId);
|
return handler.SendCloseWindow(windowId);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1573,6 +1573,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
case WindowActionType.LeftClick: button = 0; break;
|
case WindowActionType.LeftClick: button = 0; break;
|
||||||
case WindowActionType.RightClick: button = 1; break;
|
case WindowActionType.RightClick: button = 1; break;
|
||||||
case WindowActionType.MiddleClick: button = 2; mode = 3; break;
|
case WindowActionType.MiddleClick: button = 2; mode = 3; break;
|
||||||
|
case WindowActionType.ShiftClick: button = 0; mode = 1; break;
|
||||||
case WindowActionType.DropItem:
|
case WindowActionType.DropItem:
|
||||||
button = 0;
|
button = 0;
|
||||||
mode = 4;
|
mode = 4;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue