Item stack size is now defined by ItemSlot, not ItemData

This commit is contained in:
OLEGSHA 2021-08-28 21:07:08 +03:00
parent 2fe84dc59e
commit b3ac7b6afe
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
6 changed files with 97 additions and 97 deletions

View File

@ -17,87 +17,32 @@
*/ */
package ru.windcorp.progressia.common.world.item; package ru.windcorp.progressia.common.world.item;
import ru.windcorp.progressia.common.state.IntStateField;
import ru.windcorp.progressia.common.state.StatefulObject; import ru.windcorp.progressia.common.state.StatefulObject;
import ru.windcorp.progressia.common.world.generic.ItemGeneric; import ru.windcorp.progressia.common.world.generic.ItemGeneric;
/** /**
* A collection of identical items identified by their ID, properties and * An item identified by its ID and properties, able to reside in a slot.
* amount, able to reside in a slot. Also known as an item stack.
* <p>
* An empty stack does not have an {@code ItemData} representation; stack size
* is at least 1.
*/ */
public abstract class ItemData extends StatefulObject implements ItemGeneric { public abstract class ItemData extends StatefulObject implements ItemGeneric {
private final IntStateField size = field("Core:Size").setShared().ofInt().build();
public ItemData(String id) { public ItemData(String id) {
super(ItemDataRegistry.getInstance(), id); super(ItemDataRegistry.getInstance(), id);
size.setNow(this, 1);
} }
/** /**
* Returns the amount of individual items represented by this item stack. * Computes and returns the mass of a single unit (single item) of this
* item.
* *
* @return the size of this stack * @return the mass of this item
*/ */
public final int getSize() { public abstract float getMass();
return size.get(this);
}
/**
* Sets the amount of items represented by this item stack.
*
* @param size the new size of this stack, strictly positive
*/
public final void setSizeNow(int size) {
if (size <= 0) {
throw new IllegalArgumentException("size cannot be negative, given size " + size);
}
this.size.setNow(this, size);
}
/**
* Computes and returns the total mass of this item stack. It is defined as
* the item's unit mass (see {@link #getUnitMass()}) multiplied by the
* amount of items in the stack.
*
* @return the mass of this stack
* @see #getUnitMass()
*/
public final float getMass() {
return getUnitMass() * getSize();
}
/**
* Computes and returns the mass of a single unit (single item) of this item
* stack.
*
* @return the mass of a single item in this stack
* @see #getMass()
*/
public abstract float getUnitMass();
/**
* Computes and returns the total volume of this item stack. It is defined
* as the item's unit volume (see {@link #getUnitVolume()}) multiplied by
* the amount of items in the stack.
*
* @return the mass of this stack
* @see #getUnitVolume()
*/
public final float getVolume() {
return getUnitVolume() * getSize();
}
/** /**
* Computes and returns the volume of a single unit (single item) of this * Computes and returns the volume of a single unit (single item) of this
* item stack. * item stack.
* *
* @return the volume of a single item in this stack * @return the volume of this item
* @see #getVolume()
*/ */
public abstract float getUnitVolume(); public abstract float getVolume();
} }

View File

@ -19,23 +19,23 @@ package ru.windcorp.progressia.common.world.item;
public class ItemDataSimple extends ItemData { public class ItemDataSimple extends ItemData {
private final float unitMass; private final float mass;
private final float unitVolume; private final float volume;
public ItemDataSimple(String id, float unitMass, float unitVolume) { public ItemDataSimple(String id, float mass, float volume) {
super(id); super(id);
this.unitMass = unitMass; this.mass = mass;
this.unitVolume = unitVolume; this.volume = volume;
} }
@Override @Override
public float getUnitMass() { public float getMass() {
return unitMass; return mass;
} }
@Override @Override
public float getUnitVolume() { public float getVolume() {
return unitVolume; return volume;
} }
} }

View File

@ -31,6 +31,7 @@ import ru.windcorp.progressia.common.state.IOContext;
public class ItemSlot implements Encodable { public class ItemSlot implements Encodable {
private ItemData contents; private ItemData contents;
private int amount;
/** /**
* Retrieves the contents of this slot. * Retrieves the contents of this slot.
@ -43,29 +44,87 @@ public class ItemSlot implements Encodable {
/** /**
* Sets the new contents of this slot. If an item stack was present * Sets the new contents of this slot. If an item stack was present
* previously, it is discarded. * previously, it is discarded. If the contents are {@code null}, the slot
* is emptied.
* <p>
* When the slot receives non-null contents, the new amount must be a
* positive integer. When the slot is emptied, {@code amount} must be 0.
* *
* @param contents the new contents of this slot or {@code null} to clear * @param contents the new contents of this slot or {@code null} to clear
* the slot * the slot
* @param amount the amount of items to set.
* {@code (amount == 0) == (contents == null)} must be true.
*/ */
public synchronized final void setContents(ItemData contents) { public synchronized final void setContents(ItemData contents, int amount) {
this.contents = contents; this.contents = contents;
this.amount = amount;
checkState();
}
/**
* Sets the amount of items stored in this slot.
* <p>
* Setting the amount to zero also erases the slot's contents.
*
* @param amount the new amount
*/
public synchronized void setAmount(int amount) {
setContents(amount == 0 ? null : contents, amount);
}
/**
* Clears this slot
*/
public synchronized void clear() {
setContents(null, 0);
}
/**
* Retrieves the amount of items stored in this slot. If not items are
* present, this returns 0.
*
* @return the amount of items stored
*/
public synchronized int getAmount() {
return amount;
}
public synchronized boolean isEmpty() {
return amount == 0;
}
private synchronized void checkState() {
if ((contents == null) != (amount == 0)) {
if (contents == null) {
throw new IllegalArgumentException("Contents is null but amount (" + amount + ") != 0");
} else {
throw new IllegalArgumentException("Contents is " + contents + " but amount is zero");
}
}
if (amount < 0) {
throw new IllegalArgumentException("amount is negative: " + amount);
}
} }
@Override @Override
public synchronized void read(DataInput input, IOContext context) throws IOException { public synchronized void read(DataInput input, IOContext context) throws IOException {
if (input.readBoolean()) { amount = input.readInt();
if (amount != 0) {
String id = input.readUTF(); String id = input.readUTF();
contents = ItemDataRegistry.getInstance().create(id); contents = ItemDataRegistry.getInstance().create(id);
contents.read(input, context); contents.read(input, context);
} else { } else {
contents = null; contents = null;
} }
checkState();
} }
@Override @Override
public synchronized void write(DataOutput output, IOContext context) throws IOException { public synchronized void write(DataOutput output, IOContext context) throws IOException {
output.writeBoolean(contents != null); output.writeInt(amount);
if (contents != null) { if (contents != null) {
output.writeUTF(contents.getId()); output.writeUTF(contents.getId());
contents.write(output, context); contents.write(output, context);
@ -76,6 +135,8 @@ public class ItemSlot implements Encodable {
public void copy(Encodable destination) { public void copy(Encodable destination) {
ItemSlot slot = (ItemSlot) destination; ItemSlot slot = (ItemSlot) destination;
slot.amount = this.amount;
if (this.contents == null) { if (this.contents == null) {
slot.contents = null; slot.contents = null;
} else { } else {

View File

@ -27,7 +27,6 @@ import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; import ru.windcorp.progressia.common.world.entity.EntityDataRegistry;
import ru.windcorp.progressia.common.world.item.ItemData;
import ru.windcorp.progressia.common.world.item.ItemDataRegistry; import ru.windcorp.progressia.common.world.item.ItemDataRegistry;
import ru.windcorp.progressia.server.events.PlayerJoinedEvent; import ru.windcorp.progressia.server.events.PlayerJoinedEvent;
import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestContent;
@ -66,16 +65,8 @@ public class PlayerManager {
player.getInventory().addSlots(10); player.getInventory().addSlots(10);
ItemData stack = ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"); player.getInventory().getSlot(3).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"), 5);
stack.setSizeNow(5); player.getInventory().getSlot(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"), 1);
player.getInventory().getSlot(3).setContents(stack);
player.getInventory().getSlot(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"));
player.getLeftHand().getSlot(0).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"));
stack = ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream");
stack.setSizeNow(64);
player.getRightHand().getSlot(0).setContents(stack);
player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation()); player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation());
player.setUpVector(new Vec3(0, 0, 1)); player.setUpVector(new Vec3(0, 0, 1));

View File

@ -148,10 +148,13 @@ public class InventoryScreen extends Component {
ItemSlot from = ((DecoratedSlotComponent) button).getSlot(); ItemSlot from = ((DecoratedSlotComponent) button).getSlot();
ItemData fromData = from.getContents(); ItemData fromData = from.getContents();
int fromAmount = from.getAmount();
ItemData toData = to.getContents(); ItemData toData = to.getContents();
int toAmount = to.getAmount();
from.setContents(toData); from.setContents(toData, toAmount);
to.setContents(fromData); to.setContents(fromData, fromAmount);
requestReassembly(); requestReassembly();

View File

@ -39,8 +39,8 @@ public class SlotComponent extends Component {
private ItemRenderable itemRenderer = null; private ItemRenderable itemRenderer = null;
private int sizeDisplayInt = 0; private int amountDisplayInt = 0;
private String sizeDisplayString = ""; private String amountDisplayString = "";
public SlotComponent(String name, ItemContainer container, int index) { public SlotComponent(String name, ItemContainer container, int index) {
super(name); super(name);
@ -51,7 +51,7 @@ public class SlotComponent extends Component {
setPreferredSize(side, side); setPreferredSize(side, side);
Font sizeFont = new Font().deriveOutlined().withScale(1); Font sizeFont = new Font().deriveOutlined().withScale(1);
addChild(new DynamicLabel(name + ".Size", sizeFont, () -> sizeDisplayString, side)); addChild(new DynamicLabel(name + ".Size", sizeFont, () -> amountDisplayString, side));
setLayout(new LayoutAlign(0, 0, 0)); setLayout(new LayoutAlign(0, 0, 0));
} }
@ -74,17 +74,17 @@ public class SlotComponent extends Component {
if (contents == null) { if (contents == null) {
itemRenderer = null; itemRenderer = null;
sizeDisplayInt = 0; amountDisplayInt = 0;
sizeDisplayString = ""; amountDisplayString = "";
} else { } else {
if (itemRenderer == null || itemRenderer.getData() != contents) { if (itemRenderer == null || itemRenderer.getData() != contents) {
itemRenderer = ItemRenderRegistry.getInstance().get(contents.getId()).createRenderable(contents); itemRenderer = ItemRenderRegistry.getInstance().get(contents.getId()).createRenderable(contents);
} }
int newSize = contents.getSize(); int newAmount = getSlot().getAmount();
if (newSize != sizeDisplayInt) { if (newAmount != amountDisplayInt) {
sizeDisplayInt = newSize; amountDisplayInt = newAmount;
sizeDisplayString = newSize == 1 ? "" : Integer.toString(newSize); amountDisplayString = newAmount == 1 ? "" : Integer.toString(newAmount);
} }
} }
} }