Skip to content

Commit

Permalink
Inventory combine/swap commands now work with containers.
Browse files Browse the repository at this point in the history
  • Loading branch information
DaveyBiggers committed Jul 17, 2017
1 parent fce5345 commit a0598b3
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,28 @@

package com.microsoft.Malmo.MissionHandlers;

import io.netty.buffer.ByteBuf;

import java.util.ArrayList;
import java.util.List;

import com.microsoft.Malmo.MalmoMod;
import com.microsoft.Malmo.Schemas.InventoryCommand;
import com.microsoft.Malmo.Schemas.InventoryCommands;
import com.microsoft.Malmo.Schemas.MissionInit;

import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityLockableLoot;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

import com.microsoft.Malmo.MalmoMod;
import com.microsoft.Malmo.Schemas.InventoryCommand;
import com.microsoft.Malmo.Schemas.InventoryCommands;
import com.microsoft.Malmo.Schemas.MissionInit;

/** Very basic control over inventory. Two commands are required: select and drop - each takes a slot.<br>
* The effect is to swap the item stacks over - eg "select 10" followed by "drop 0" will swap the stacks
* in slots 0 and 10.<br>
Expand All @@ -52,17 +55,20 @@ public static class InventoryMessage implements IMessage
int slotA;
int slotB;
boolean combine;
BlockPos containerPos;

public InventoryMessage()
{
}

public InventoryMessage(String inva, int a, String invb, int b, boolean combine)
public InventoryMessage(List<Object> params, boolean combine)
{
this.invA = inva;
this.slotA = a;
this.invB = invb;
this.slotB = b;
this.invA = (String)params.get(0);
this.slotA = (Integer)params.get(1);
this.invB = (String)params.get(2);
this.slotB = (Integer)params.get(3);
if (params.size() == 5)
this.containerPos = (BlockPos)params.get(4);
this.combine = combine;
}

Expand All @@ -74,6 +80,8 @@ public void fromBytes(ByteBuf buf)
this.invB = ByteBufUtils.readUTF8String(buf);
this.slotB = buf.readInt();
this.combine = buf.readBoolean();
if (buf.readBoolean())
this.containerPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
}

@Override
Expand All @@ -84,6 +92,13 @@ public void toBytes(ByteBuf buf)
ByteBufUtils.writeUTF8String(buf, this.invB);
buf.writeInt(this.slotB);
buf.writeBoolean(this.combine);
buf.writeBoolean(this.containerPos != null);
if (this.containerPos != null)
{
buf.writeInt(this.containerPos.getX());
buf.writeInt(this.containerPos.getY());
buf.writeInt(this.containerPos.getZ());
}
}
}

Expand All @@ -94,9 +109,9 @@ public IMessage onMessage(InventoryMessage message, MessageContext ctx)
{
EntityPlayerMP player = ctx.getServerHandler().playerEntity;
if (message.combine)
combineSlots(player, message.invA, message.slotA, message.invB, message.slotB);
combineSlots(player, message.invA, message.slotA, message.invB, message.slotB, message.containerPos);
else
swapSlots(player, message.invA, message.slotA, message.invB, message.slotB);
swapSlots(player, message.invA, message.slotA, message.invB, message.slotB, message.containerPos);
return null;
}
}
Expand All @@ -120,31 +135,47 @@ public boolean parseParameters(Object params)
return true;
}

static void combineSlots(EntityPlayerMP player, String invDst, int dst, String invAdd, int add)
static void combineSlots(EntityPlayerMP player, String invDst, int dst, String invAdd, int add, BlockPos containerPos)
{
InventoryPlayer inv = player.inventory;
ItemStack dstStack = inv.getStackInSlot(dst);
ItemStack addStack = inv.getStackInSlot(add);
IInventory container = null;
String containerName = "";
if (containerPos != null)
{
TileEntity te = player.world.getTileEntity(containerPos);
if (te != null && te instanceof TileEntityLockableLoot)
{
TileEntityLockableLoot tell = (TileEntityLockableLoot) te;
containerName = tell.getName();
container = tell;
}
}
IInventory dstInv = invDst.equals("inventory") ? player.inventory : (invDst.equals(containerName) ? container : null);
IInventory addInv = invAdd.equals("inventory") ? player.inventory : (invAdd.equals(containerName) ? container : null);
if (dstInv == null || addInv == null)
return; // Source or dest container not available.

ItemStack dstStack = dstInv.getStackInSlot(dst);
ItemStack addStack = addInv.getStackInSlot(add);

if (addStack == null)
return; // Combination is a no-op.
return; // Combination is a no-op.

if (dstStack == null) // Do a straight move - nothing to combine with.
if (dstStack == null) // Do a straight move - nothing to combine with.
{
inv.setInventorySlotContents(dst, addStack);
inv.setInventorySlotContents(add, null);
dstInv.setInventorySlotContents(dst, addStack);
addInv.setInventorySlotContents(add, null);
return;
}

// Check we can combine. This logic comes from InventoryPlayer.storeItemStack():
boolean itemsMatch = dstStack.getItem() == addStack.getItem();
boolean dstCanStack = dstStack.isStackable() && dstStack.getCount() < dstStack.getMaxStackSize() && dstStack.getCount() < inv.getInventoryStackLimit();
boolean dstCanStack = dstStack.isStackable() && dstStack.getCount() < dstStack.getMaxStackSize() && dstStack.getCount() < dstInv.getInventoryStackLimit();
boolean subTypesMatch = !dstStack.getHasSubtypes() || dstStack.getMetadata() == addStack.getMetadata();
boolean tagsMatch = ItemStack.areItemStackTagsEqual(dstStack, addStack);
if (itemsMatch && dstCanStack && subTypesMatch && tagsMatch)
{
// We can combine, so figure out how much we have room for:
int limit = Math.min(dstStack.getMaxStackSize(), inv.getInventoryStackLimit());
int limit = Math.min(dstStack.getMaxStackSize(), dstInv.getInventoryStackLimit());
int room = limit - dstStack.getCount();
if (addStack.getCount() > room)
{
Expand All @@ -156,18 +187,37 @@ static void combineSlots(EntityPlayerMP player, String invDst, int dst, String i
{
// Room for the whole lot, so empty out the add slot.
dstStack.setCount(dstStack.getCount() + addStack.getCount());
inv.setInventorySlotContents(add, null);
addInv.setInventorySlotContents(add, null);
}
}
}

static void swapSlots(EntityPlayerMP player, String lhsInv, int lhs, String rhsInv, int rhs)
static void swapSlots(EntityPlayerMP player, String lhsInv, int lhs, String rhsInv, int rhs, BlockPos containerPos)
{
InventoryPlayer inv = player.inventory;
ItemStack srcStack = inv.getStackInSlot(lhs);
ItemStack dstStack = inv.getStackInSlot(rhs);
inv.setInventorySlotContents(lhs, dstStack);
inv.setInventorySlotContents(rhs, srcStack);
IInventory container = null;
String containerName = "";
if (containerPos != null)
{
TileEntity te = player.world.getTileEntity(containerPos);
if (te != null && te instanceof TileEntityLockableLoot)
{
TileEntityLockableLoot tell = (TileEntityLockableLoot) te;
containerName = tell.getName();
String prefix = "container.";
if (containerName.startsWith(prefix))
containerName = containerName.substring(prefix.length());
container = tell;
}
}
IInventory lhsInventory = lhsInv.equals("inventory") ? player.inventory : (lhsInv.equals(containerName) ? container : null);
IInventory rhsInventory = rhsInv.equals("inventory") ? player.inventory : (rhsInv.equals(containerName) ? container : null);
if (lhsInventory == null || rhsInventory == null)
return; // Source or dest container not available.

ItemStack srcStack = lhsInventory.getStackInSlot(lhs);
ItemStack dstStack = rhsInventory.getStackInSlot(rhs);
lhsInventory.setInventorySlotContents(lhs, dstStack);
rhsInventory.setInventorySlotContents(rhs, srcStack);
}

@Override
Expand All @@ -177,11 +227,11 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn
{
if (parameter != null && parameter.length() != 0)
{
List<String> params = new ArrayList<String>();
List<Object> params = new ArrayList<Object>();
if (getParameters(parameter, params))
{
// All okay, so create a swap message for the server:
MalmoMod.network.sendToServer(new InventoryMessage(params.get(0), Integer.valueOf(params.get(1)), params.get(2), Integer.valueOf(params.get(3)), false));
MalmoMod.network.sendToServer(new InventoryMessage(params, false));
return true;
}
else
Expand All @@ -192,11 +242,11 @@ else if (verb.equalsIgnoreCase(InventoryCommand.COMBINE_INVENTORY_ITEMS.value())
{
if (parameter != null && parameter.length() != 0)
{
List<String> params = new ArrayList<String>();
List<Object> params = new ArrayList<Object>();
if (getParameters(parameter, params))
{
// All okay, so create a combine message for the server:
MalmoMod.network.sendToServer(new InventoryMessage(params.get(0), Integer.valueOf(params.get(1)), params.get(2), Integer.valueOf(params.get(3)), true));
MalmoMod.network.sendToServer(new InventoryMessage(params, true));
return true;
}
else
Expand All @@ -212,7 +262,7 @@ else if (verb.equalsIgnoreCase(InventoryCommand.DISCARD_CURRENT_ITEM.value()))
return super.onExecute(verb, parameter, missionInit);
}

private boolean getParameters(String parameter, List<String> parsedParams)
private boolean getParameters(String parameter, List<Object> parsedParams)
{
String[] params = parameter.split(" ");
if (params.length != 2)
Expand All @@ -224,10 +274,12 @@ private boolean getParameters(String parameter, List<String> parsedParams)
String[] rhsParams = params[1].split(":");
Integer lhsIndex, rhsIndex;
String lhsName, rhsName, lhsStrIndex, rhsStrIndex;
boolean checkContainers = false;
if (lhsParams.length == 2)
{
lhsName = lhsParams[0];
lhsStrIndex = lhsParams[1];
checkContainers = true;
}
else if (lhsParams.length == 1)
{
Expand All @@ -243,6 +295,7 @@ else if (lhsParams.length == 1)
{
rhsName = rhsParams[0];
rhsStrIndex = rhsParams[1];
checkContainers = true;
}
else if (rhsParams.length == 1)
{
Expand Down Expand Up @@ -270,11 +323,37 @@ else if (rhsParams.length == 1)
System.out.println("Malformed parameter string (" + parameter + ")");
return false; // Error - incorrect parameters.
}
BlockPos containerPos = null;
if (checkContainers)
{
String containerName = "";
RayTraceResult rtr = Minecraft.getMinecraft().objectMouseOver;
if (rtr != null && rtr.typeOfHit == RayTraceResult.Type.BLOCK)
{
containerPos = rtr.getBlockPos();
TileEntity te = Minecraft.getMinecraft().world.getTileEntity(containerPos);
if (te instanceof TileEntityLockableLoot)
{
containerName = ((TileEntityLockableLoot) te).getName();
String prefix = "container.";
if (containerName.startsWith(prefix))
containerName = containerName.substring(prefix.length());
}
}
boolean containerMatches = (lhsName.equals("inventory") || lhsName.equals(containerName)) && (rhsName.equals("inventory") || rhsName.equals(containerName));
if (!containerMatches)
{
System.out.println("Missing container requested in parameter string (" + parameter + ")");
return false;
}
}

parsedParams.add(lhsName);
parsedParams.add(lhsStrIndex);
parsedParams.add(lhsIndex);
parsedParams.add(rhsName);
parsedParams.add(rhsStrIndex);
parsedParams.add(rhsIndex);
if (containerPos != null)
parsedParams.add(containerPos);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@

package com.microsoft.Malmo.MissionHandlers;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.microsoft.Malmo.Schemas.DrawItem;
import com.microsoft.Malmo.Schemas.MissionInit;
import com.microsoft.Malmo.Schemas.ObservationFromFullInventory;
import com.microsoft.Malmo.Utils.MinecraftTypeHelper;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
Expand All @@ -34,13 +39,6 @@
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.microsoft.Malmo.Schemas.DrawItem;
import com.microsoft.Malmo.Schemas.MissionInit;
import com.microsoft.Malmo.Schemas.ObservationFromFullInventory;
import com.microsoft.Malmo.Utils.MinecraftTypeHelper;

/** Simple IObservationProducer class that returns a list of the full inventory, including the armour.
*/
public class ObservationFromFullInventoryImplementation extends ObservationFromServer
Expand Down

0 comments on commit a0598b3

Please sign in to comment.