refactor for inventories, allowing for null types.

This commit is contained in:
gnembon committed 2020-11-26 00:33:09 -04:00
1 parent 2d92a82ed0
commit 79cb4a20d8
3 files changed
+76 -62

No files matched your search

+29 -16
View File
@@ -3,29 +3,30 @@
## Manipulating inventories of blocks and entities ## Manipulating inventories of blocks and entities
Most functions in this category require inventory as the first argument. Inventory could be specified by an entity, Most functions in this category require inventory as the first argument. Inventory could be specified by an entity,
or a block, or position (three coordinates) of a potential block with inventory. Player enderchest inventory require or a block, or position (three coordinates) of a potential block with inventory, or can be preceded with inventory
two arguments, keyword `'enderchest'`, followed by the player entity argument, or a single argument as a string of a type.
form: `'enderchest_steve'`. If your player name starts with enderchest, it can be always accessed by passing a player Inventory type can be `null` (default), `'enderchest'` denoting player enderchest storage, or `'equipment'` applying to
entities hand and armour pieces. Then the type can be followed by entity, block or position coordinates.
For instance, player enderchest inventory requires
two arguments, keyword `'enderchest'`, followed by the player entity argument, (or a single argument as a string of a
form: `'enderchest_steve'` for legacy support). If your player name starts with `'enderchest_'`, first of all, tough luck,
but then it can be always accessed by passing a player
entity value. If all else fails, it will try to identify first three arguments as coordinates of a block position of entity value. If all else fails, it will try to identify first three arguments as coordinates of a block position of
a block inventory. Player inventories can also be called by their name. a block inventory. Player inventories can also be called by their name.
You can also use `'equipment'` as a keyword preceeding an entity indicating the need of access that entity as a mob. A few living entities can have both: their regular inventory, and their equipment inventory.
Equipment inventory Player's regular inventory already contains the equipment, but you can access the equipment part as well, as well as
consists of its armour and hand items, and a few living entites can have both, their regular inventory, and their equipment inventory. For some their enderchest separately. For entity types that only have
entities (players) their regular inventory already contains the equipment. For entity types that only have their equipment inventory, the equipment is returned by default (`null` type).
their equipment inventory, the equipment is returned by default.
If that's confusing see examples under `inventory_size` on how to access inventories. All other `inventory_...()` functions
use the same scheme.
<pre>
inventory_size(player()) => 41 // items
inventory_size('enderchest', player()) => 27 // equipment
inventory_size('equipment', player()) => 6 // equipment
</pre>
If the entity or a block doesn't have If the entity or a block doesn't have
an inventory, they typically do nothing and return null. an inventory, all API functions typically do nothing and return null.
Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item. Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item.
Manipulating of the nbt data can be costly, but retrieving them from the tuple to match other aspects is cheap
### `stack_limit(item)` ### `stack_limit(item)`
@@ -98,14 +99,26 @@ item name that serves as a replacement after crafting is done. Currently it can
### `inventory_size(inventory)` ### `inventory_size(inventory)`
Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't
have an inventory have an inventory.
<pre> <pre>
inventory_size(player()) => 41 inventory_size(player()) => 41
inventory_size('enderchest', player()) => 27 // enderchest inventory_size('enderchest', player()) => 27 // enderchest
inventory_size('equipment', player()) => 6 // equipment inventory_size('equipment', player()) => 6 // equipment
inventory_size(null, player()) => 41 // default inventory for players
inventory_size(x,y,z) => 27 // chest inventory_size(x,y,z) => 27 // chest
inventory_size(block(pos)) => 5 // hopper inventory_size(block(pos)) => 5 // hopper
horse = spawn('horse', x, y, z);
inventory_size(horse); => 2 // default horse inventory
inventory_size('equipment', horse); => 6 // unused horse equipment inventory
inventory_size(null, horse); => 2 // default horse
creeper = spawn('creeper', x, y, z);
inventory_size(creeper); => 6 // default creeper inventory is equipment since it has no other
inventory_size('equipment', creeper); => 6 // unused horse equipment inventory
inventory_size(null, creeper); => 6 // creeper default is its equipment
</pre> </pre>
### `inventory_has_items(inventory)` ### `inventory_has_items(inventory)`
@@ -9,7 +9,7 @@ import net.minecraft.item.ItemStack;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public class LivingInventory implements Inventory public class EquipmentInventory implements Inventory
{ {
private static final List<EquipmentSlot> slotToSlot = Arrays.asList( private static final List<EquipmentSlot> slotToSlot = Arrays.asList(
EquipmentSlot.MAINHAND, EquipmentSlot.MAINHAND,
@@ -18,7 +18,7 @@ public class LivingInventory implements Inventory
); );
LivingEntity mob; LivingEntity mob;
public LivingInventory(LivingEntity mob) public EquipmentInventory(LivingEntity mob)
{ {
this.mob = mob; this.mob = mob;
} }
@@ -4,7 +4,7 @@ import carpet.fakes.InventoryBearerInterface;
import carpet.script.CarpetContext; import carpet.script.CarpetContext;
import carpet.script.LazyValue; import carpet.script.LazyValue;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import carpet.script.utils.LivingInventory; import carpet.script.utils.EquipmentInventory;
import com.mojang.brigadier.StringReader; import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@@ -175,47 +175,15 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
return inventory; return inventory;
} }
public static InventoryLocator locateInventory(CarpetContext c, List<LazyValue> params, int offset) public static InventoryLocator locateInventory(CarpetContext c, List<LazyValue> params, int offset)
{ {
try try
{ {
Inventory inv = null; Value v1 = params.get(offset).evalValue(c);
Value v1 = params.get(0 + offset).evalValue(c); if (v1.isNull())
if (v1 instanceof EntityValue)
{ {
Entity e = ((EntityValue) v1).getEntity(); offset ++;
if (e instanceof PlayerEntity) inv = ((PlayerEntity) e).inventory; v1 = params.get(offset).evalValue(c);
else if (e instanceof Inventory) inv = (Inventory) e;
else if (e instanceof VillagerEntity) inv = ((VillagerEntity) e).getInventory();
else if (e instanceof InventoryBearerInterface) inv = ((InventoryBearerInterface)e).getCMInventory();
else if (e instanceof LivingEntity) inv = new LivingInventory((MobEntity) e);
if (inv == null)
return null;
return new InventoryLocator(e, e.getBlockPos(), inv, offset + 1);
}
else if (v1 instanceof BlockValue)
{
BlockPos pos = ((BlockValue) v1).getPos();
if (pos == null)
throw new InternalExpressionException("Block to access inventory needs to be positioned in the world");
inv = getInventoryAt(c.s.getWorld(), pos);
if (inv == null)
return null;
return new InventoryLocator(pos, pos, inv, offset + 1);
}
else if (v1 instanceof ListValue)
{
List<Value> args = ((ListValue) v1).getItems();
BlockPos pos = new BlockPos(
NumericValue.asNumber(args.get(0)).getDouble(),
NumericValue.asNumber(args.get(1)).getDouble(),
NumericValue.asNumber(args.get(2)).getDouble());
inv = getInventoryAt(c.s.getWorld(), pos);
if (inv == null)
return null;
return new InventoryLocator(pos, pos, inv, offset + 1);
} }
else if (v1 instanceof StringValue) else if (v1 instanceof StringValue)
{ {
@@ -227,16 +195,14 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
if (player == null) throw new InternalExpressionException("enderchest inventory requires player argument"); if (player == null) throw new InternalExpressionException("enderchest inventory requires player argument");
return new InventoryLocator(player, player.getBlockPos(), player.getEnderChestInventory(), offset + 2, true); return new InventoryLocator(player, player.getBlockPos(), player.getEnderChestInventory(), offset + 2, true);
} }
else if (strVal.equals("equipment")) if (strVal.equals("equipment"))
{ {
Value v2 = params.get(1 + offset).evalValue(c); Value v2 = params.get(1 + offset).evalValue(c);
if (!(v2 instanceof EntityValue)) throw new InternalExpressionException("mob inventory requires a mob argument"); if (!(v2 instanceof EntityValue)) throw new InternalExpressionException("Equipment inventory requires a living entity argument");
Entity e = ((EntityValue) v2).getEntity(); Entity e = ((EntityValue) v2).getEntity();
if (!(e instanceof LivingEntity)) throw new InternalExpressionException("mob inventory requires a mob argument"); if (!(e instanceof LivingEntity)) throw new InternalExpressionException("Equipment inventory requires a living entity argument");
return new InventoryLocator(e, e.getBlockPos(), new LivingInventory((LivingEntity) e), offset + 2, false); return new InventoryLocator(e, e.getBlockPos(), new EquipmentInventory((LivingEntity) e), offset + 2);
} }
else
{
boolean isEnder = strVal.startsWith("enderchest_"); boolean isEnder = strVal.startsWith("enderchest_");
if (isEnder) strVal = strVal.substring(11); // len("enderchest_") if (isEnder) strVal = strVal.substring(11); // len("enderchest_")
ServerPlayerEntity player = c.s.getMinecraftServer().getPlayerManager().getPlayer(strVal); ServerPlayerEntity player = c.s.getMinecraftServer().getPlayerManager().getPlayer(strVal);
@@ -249,12 +215,47 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
isEnder isEnder
); );
} }
if (v1 instanceof EntityValue)
{
Inventory inv = null;
Entity e = ((EntityValue) v1).getEntity();
if (e instanceof PlayerEntity) inv = ((PlayerEntity) e).inventory;
else if (e instanceof Inventory) inv = (Inventory) e;
else if (e instanceof VillagerEntity) inv = ((VillagerEntity) e).getInventory();
else if (e instanceof InventoryBearerInterface) inv = ((InventoryBearerInterface)e).getCMInventory();
else if (e instanceof LivingEntity) return new InventoryLocator(e, e.getBlockPos(), new EquipmentInventory((MobEntity) e), offset+1);
if (inv == null)
return null;
return new InventoryLocator(e, e.getBlockPos(), inv, offset+1);
}
if (v1 instanceof BlockValue)
{
BlockPos pos = ((BlockValue) v1).getPos();
if (pos == null)
throw new InternalExpressionException("Block to access inventory needs to be positioned in the world");
Inventory inv = getInventoryAt(c.s.getWorld(), pos);
if (inv == null)
return null;
return new InventoryLocator(pos, pos, inv, offset+1);
}
if (v1 instanceof ListValue)
{
List<Value> args = ((ListValue) v1).getItems();
BlockPos pos = new BlockPos(
NumericValue.asNumber(args.get(0)).getDouble(),
NumericValue.asNumber(args.get(1)).getDouble(),
NumericValue.asNumber(args.get(2)).getDouble());
Inventory inv = getInventoryAt(c.s.getWorld(), pos);
if (inv == null)
return null;
return new InventoryLocator(pos, pos, inv, offset+1);
} }
BlockPos pos = new BlockPos( BlockPos pos = new BlockPos(
NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v1).getDouble(),
NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(),
NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble());
inv = getInventoryAt(c.s.getWorld(), pos); Inventory inv = getInventoryAt(c.s.getWorld(), pos);
if (inv == null) if (inv == null)
return null; return null;
return new InventoryLocator(pos, pos, inv, offset + 3); return new InventoryLocator(pos, pos, inv, offset + 3);