Remove some debug info, make it so StoredObject protects user.

Implement rewriting of Slot in rewriter.
Implement Enchanting Patch
Implement Brewing Patch
Implement Auto-Team Patch
Implement Inventory Tracker
Remove some TODOs
Implement Item Throwing on elytra
(Should just be plugin channels and a few packets + sounds left)
This commit is contained in:
Myles 2016-03-16 23:34:03 +00:00
parent 7e133a0be8
commit ccda9f11c8
13 changed files with 261 additions and 59 deletions

View File

@ -91,8 +91,7 @@ public class PacketWrapper {
}
int index = 0;
for (Pair<Type, Object> packetValue : packetValues) {
System.out.println("writing: " + packetValue.getKey().getTypeName() + " value: " + packetValue.getValue() + " ID: " + getId());
try {
try {
Object value = packetValue.getValue();
if (value != null) {
if (!value.getClass().equals(packetValue.getKey().getOutputClass())) {
@ -111,11 +110,6 @@ public class PacketWrapper {
}
index++;
}
if (packetValues.size() != 0) {
if (inputBuffer != null) {
System.out.println(">> Writing remaining: " + inputBuffer.readableBytes() + " ID: " + getId());
}
}
writeRemaining(buffer);
}

View File

@ -1,8 +1,9 @@
package us.myles.ViaVersion2.api.data;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@Getter(AccessLevel.PROTECTED)
@AllArgsConstructor
public class StoredObject {
private UserConnection user;

View File

@ -58,7 +58,6 @@ public abstract class Protocol {
packetWrapper.setId(newID);
// remap
if (protocolPacket.getRemapper() != null) {
System.out.println("Remapping for " + getClass().getName() + " - " + newID + "<- " + direction + " " + state);
protocolPacket.getRemapper().remap(packetWrapper);
if(packetWrapper.isCancelled())
throw new CancelException();

View File

@ -60,12 +60,13 @@ public class ProtocolPipeline extends Protocol {
packetWrapper.resetReader();
}
super.transform(direction, state, packetWrapper);
System.out.println("--> Sending Packet ID: " + packetWrapper.getId() + " " + state + " " + direction);
if (packetWrapper.getId() != 37 && packetWrapper.getId() != 32 && packetWrapper.getId() != 52 && packetWrapper.getId() != 21 && packetWrapper.getId() != 59)
System.out.println("--> Sending Packet ID: " + packetWrapper.getId() + " " + state + " " + direction);
}
public boolean contains(Class<? extends Protocol> pipeClass){
for(Protocol protocol:protocolList){
if(protocol.getClass().equals(pipeClass)) return true;
public boolean contains(Class<? extends Protocol> pipeClass) {
for (Protocol protocol : protocolList) {
if (protocol.getClass().equals(pipeClass)) return true;
}
return false;
}

View File

@ -13,6 +13,7 @@ import us.myles.ViaVersion2.api.protocol.base.ProtocolInfo;
import us.myles.ViaVersion2.api.protocol1_9to1_8.packets.*;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.ClientChunks;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.InventoryTracker;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.MovementTracker;
import us.myles.ViaVersion2.api.protocol1_9to1_8.types.MetadataListType;
import us.myles.ViaVersion2.api.protocol1_9to1_8.types.MetadataType;
@ -71,6 +72,8 @@ public class Protocol1_9TO1_8 extends Protocol {
userConnection.put(new ClientChunks(userConnection));
// Movement tracker
userConnection.put(new MovementTracker(userConnection));
// Inventory tracker
userConnection.put(new InventoryTracker(userConnection));
}

View File

@ -9,7 +9,9 @@ import us.myles.ViaVersion.metadata.MetaIndex;
import us.myles.ViaVersion.metadata.NewType;
import us.myles.ViaVersion.metadata.Type;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion2.api.item.Item;
import us.myles.ViaVersion2.api.metadata.Metadata;
import us.myles.ViaVersion2.api.protocol1_9to1_8.ItemRewriter;
import java.util.ArrayList;
import java.util.List;
@ -111,10 +113,7 @@ public class MetadataRewriter {
case Slot:
entry.setType(us.myles.ViaVersion2.api.type.Type.ITEM);
entry.setValue(value);
// ItemSlotRewriter.ItemStack item = (ItemSlotRewriter.ItemStack) value;
// ItemSlotRewriter.fixIdsFrom1_8To1_9(item);
// ItemSlotRewriter.writeItemStack(item, output);
// TODO
ItemRewriter.toClient((Item) entry.getValue());
break;
case Position:
entry.setType(us.myles.ViaVersion2.api.type.Type.VECTOR);
@ -156,7 +155,6 @@ public class MetadataRewriter {
}
}
}
// TODO: Holo patch and bossbar patch
}
}

View File

@ -7,6 +7,7 @@ import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.ItemRewriter;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.InventoryTracker;
import us.myles.ViaVersion2.api.remapper.PacketHandler;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
import us.myles.ViaVersion2.api.remapper.ValueCreator;
@ -23,7 +24,35 @@ public class InventoryPackets {
map(Type.SHORT); // 1 - Property Key
map(Type.SHORT); // 2 - Property Value
// TODO - Enchanting patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final short property = wrapper.get(Type.SHORT, 0);
short value = wrapper.get(Type.SHORT, 1);
InventoryTracker inventoryTracker = wrapper.user().get(InventoryTracker.class);
if (inventoryTracker.getInventory() != null) {
if (inventoryTracker.getInventory().equalsIgnoreCase("minecraft:enchanting_table")) {
if (property > 3 && property < 7) {
// Send 2 properties, splitting it into enchantID & level
final short level = (short) (value >> 8);
final short enchantID = (short) (value & 0xFF);
wrapper.create(wrapper.getId(), new ValueCreator() {
@Override
public void write(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.UNSIGNED_BYTE, windowId);
wrapper.write(Type.SHORT, property);
wrapper.write(Type.SHORT, enchantID);
}
}).send();
wrapper.set(Type.SHORT, 0, (short) (property + 3));
wrapper.set(Type.SHORT, 1, level);
}
}
}
}
});
}
});
// Window Open Packet
@ -36,8 +65,25 @@ public class InventoryPackets {
map(Type.STRING, Protocol1_9TO1_8.FIX_JSON); // 2 - Window Title
map(Type.UNSIGNED_BYTE); // 3 - Slot Count
// There is a horse parameter after this, we don't handle it and let it passthrough
// TODO - Brewing patch
// TODO - Save Inventory patch
// Inventory tracking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
String inventory = wrapper.get(Type.STRING, 0);
InventoryTracker inventoryTracker = wrapper.user().get(InventoryTracker.class);
inventoryTracker.setInventory(inventory);
}
});
// Brewing patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
String inventory = wrapper.get(Type.STRING, 0);
if (inventory.equals("minecraft:brewing_stand")) {
wrapper.set(Type.UNSIGNED_BYTE, 1, (short) (wrapper.get(Type.UNSIGNED_BYTE, 1) + 1));
}
}
});
}
});
// Window Set Slot Packet
@ -49,7 +95,6 @@ public class InventoryPackets {
map(Type.BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot ID
map(Type.ITEM); // 2 - Slot Value
// TODO Brewing patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
@ -57,6 +102,22 @@ public class InventoryPackets {
ItemRewriter.toClient(stack);
}
});
// Brewing patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
InventoryTracker inventoryTracker = wrapper.user().get(InventoryTracker.class);
short slotID = wrapper.get(Type.SHORT, 0);
if (inventoryTracker.getInventory() != null) {
if (inventoryTracker.getInventory().equals("minecraft:brewing_stand")) {
if (slotID >= 4) {
wrapper.set(Type.SHORT, 0, (short) (slotID + 1));
}
}
}
}
});
}
});
// Window Set Slots Packet
@ -67,7 +128,6 @@ public class InventoryPackets {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.ITEM_ARRAY); // 1 - Window Values
// TODO Brewing patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
@ -76,6 +136,29 @@ public class InventoryPackets {
ItemRewriter.toClient(stack);
}
});
// Brewing Patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
InventoryTracker inventoryTracker = wrapper.user().get(InventoryTracker.class);
if (inventoryTracker.getInventory() != null) {
if (inventoryTracker.getInventory().equals("minecraft:brewing_stand")) {
Item[] oldStack = wrapper.get(Type.ITEM_ARRAY, 0);
Item[] newStack = new Item[oldStack.length + 1];
for (int i = 0; i < newStack.length; i++) {
if (i > 3) {
newStack[i] = oldStack[i - 1];
} else {
if (i != 3) { // Leave index 3 blank
newStack[i] = oldStack[i];
}
}
}
wrapper.set(Type.ITEM_ARRAY, 0, newStack);
}
}
}
});
}
});
// Close Window Packet
@ -84,8 +167,14 @@ public class InventoryPackets {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
// TODO Close Inventory patch
// Inventory tracking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
InventoryTracker inventoryTracker = wrapper.user().get(InventoryTracker.class);
inventoryTracker.setInventory(null);
}
});
}
});
@ -117,8 +206,8 @@ public class InventoryPackets {
@Override
public void registerMap() {
map(Type.SHORT);
map(Type.ITEM);
map(Type.SHORT); // 0 - Slot ID
map(Type.ITEM); // 1 - Item
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
@ -134,12 +223,12 @@ public class InventoryPackets {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.BYTE);
map(Type.SHORT);
map(Type.BYTE);
map(Type.ITEM);
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot ID
map(Type.BYTE); // 2 - Button
map(Type.SHORT); // 3 - Action
map(Type.BYTE); // 4 - Mode
map(Type.ITEM); // 5 - Clicked Item
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
@ -147,7 +236,42 @@ public class InventoryPackets {
ItemRewriter.toServer(stack);
}
});
// TODO: Throw elytra and brewing patch
// Brewing patch and elytra throw patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
final short windowID = wrapper.get(Type.UNSIGNED_BYTE, 0);
final short slot = wrapper.get(Type.SHORT, 0);
boolean throwItem = (slot == 45 && windowID == 0);
InventoryTracker inventoryTracker = wrapper.user().get(InventoryTracker.class);
if (inventoryTracker.getInventory() != null) {
if (inventoryTracker.getInventory().equals("minecraft:brewing_stand")) {
if (slot == 4) {
throwItem = true;
}
if (slot > 4) {
wrapper.set(Type.SHORT, 0, (short) (slot - 1));
}
}
}
if (throwItem) {
// Send a packet wiping the slot
wrapper.create(0x16, new ValueCreator() {
@Override
public void write(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.UNSIGNED_BYTE, windowID);
wrapper.write(Type.SHORT, slot);
wrapper.write(Type.SHORT, (short) -1);
}
}).send();
// Finally reset to simulate throwing item
wrapper.set(Type.BYTE, 0, (byte) 0); // Set button to 0
wrapper.set(Type.BYTE, 1, (byte) 0); // Set mode to 0
wrapper.set(Type.SHORT, 0, (short) -999); // Set slot to -999
}
}
});
}
});
@ -156,7 +280,14 @@ public class InventoryPackets {
@Override
public void registerMap() {
// TODO Close Inventory patch
// Inventory tracking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
InventoryTracker inventoryTracker = wrapper.user().get(InventoryTracker.class);
inventoryTracker.setInventory(null);
}
});
}
});
@ -165,6 +296,7 @@ public class InventoryPackets {
protocol.registerIncoming(State.PLAY, 0x0F, 0x05); // Confirm Transaction Packet
protocol.registerIncoming(State.PLAY, 0x11, 0x06); // Enchant Item Packet
// Held Item Change Packet
protocol.registerIncoming(State.PLAY, 0x09, 0x17, new PacketRemapper() {
@Override
public void registerMap() {
@ -175,11 +307,11 @@ public class InventoryPackets {
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
if (entityTracker.isBlocking()) {
entityTracker.setBlocking(false);
entityTracker.setSecondHand(wrapper.user(), null);
entityTracker.setSecondHand(null);
}
}
});
}
}); // Held Item Change Packet
});
}
}

View File

@ -8,6 +8,7 @@ import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.item.Item;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol.base.ProtocolInfo;
import us.myles.ViaVersion2.api.protocol1_9to1_8.PlayerMovementMapper;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
@ -111,7 +112,24 @@ public class PlayerPackets {
if (mode == 0 || mode == 2) {
String[] players = wrapper.read(Type.STRING_ARRAY);
// TODO Handler for sending autoteam
final EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
String myName = wrapper.user().get(ProtocolInfo.class).getUsername();
for (String player : players) {
if (entityTracker.isAutoTeam() && player.equalsIgnoreCase(myName)) {
if (mode == 4) {
// since removing add to auto team
((ViaVersionPlugin) ViaVersion.getInstance()).run(new Runnable() {
@Override
public void run() {
entityTracker.sendTeamPacket(true);
}
}, false);
} else {
// since adding remove from auto team
entityTracker.sendTeamPacket(false);
}
}
}
wrapper.write(Type.STRING_ARRAY, players);
}
}
@ -228,9 +246,6 @@ public class PlayerPackets {
protocol.registerOutgoing(State.PLAY, 0x06, 0x3E); // Update Health Packet
protocol.registerOutgoing(State.PLAY, 0x0D, 0x49); // Collect Item Packet
// TODO:
// Server Difficulty - Activate Auto-Team
/* Incoming Packets */
// Tab Complete Request Packet
@ -326,7 +341,7 @@ public class PlayerPackets {
if (!tracker.isBlocking()) {
tracker.setBlocking(true);
Item shield = new Item((short) 442, (byte) 1, (short) 0, null);
tracker.setSecondHand(wrapper.user(), shield);
tracker.setSecondHand(shield);
}
wrapper.cancel();
}

View File

@ -1,8 +1,11 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.packets;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.chunks.Chunk;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.item.Item;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.ClientChunks;
@ -94,7 +97,21 @@ public class WorldPackets {
protocol.registerOutgoing(State.PLAY, 0x27, 0x1C); // Explosion Packet
protocol.registerOutgoing(State.PLAY, 0x2A, 0x22); // Particle Packet
protocol.registerOutgoing(State.PLAY, 0x41, 0x0D); // Server Difficulty Packet
protocol.registerOutgoing(State.PLAY, 0x41, 0x0D, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (((ViaVersionPlugin) ViaVersion.getInstance()).isAutoTeam()) {
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
entityTracker.setAutoTeam(true);
entityTracker.sendTeamPacket(true);
}
}
});
}
}); // Server Difficulty Packet
protocol.registerOutgoing(State.PLAY, 0x03, 0x44); // Update Time Packet
protocol.registerOutgoing(State.PLAY, 0x44, 0x35); // World Border Packet
@ -134,9 +151,9 @@ public class WorldPackets {
int status = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (status == 5) {
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
if(entityTracker.isBlocking()){
if (entityTracker.isBlocking()) {
entityTracker.setBlocking(false);
entityTracker.setSecondHand(wrapper.user(), null);
entityTracker.setSecondHand(null);
}
}
}
@ -151,14 +168,13 @@ public class WorldPackets {
map(Type.POSITION); // 0 - Position
map(Type.VAR_INT, Type.BYTE); // 1 - Block Face
map(Type.VAR_INT, Type.NOTHING); // 2 - Hand
// TODO: Actual hand item
create(new ValueCreator() {
@Override
public void write(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.SHORT, (short) -1);
Item item = Item.getItem(Protocol1_9TO1_8.getHandItem(wrapper.user()));
wrapper.write(Type.ITEM, item);
}
});
// Did have item rewriter but its not needed
map(Type.UNSIGNED_BYTE); // 4 - X
map(Type.UNSIGNED_BYTE); // 5 - Y
map(Type.UNSIGNED_BYTE); // 6 - Z

View File

@ -11,7 +11,6 @@ import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.metadata.NewType;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.data.StoredObject;
@ -31,11 +30,13 @@ public class EntityTracker extends StoredObject {
private final Map<Integer, BossBar> bossBarMap = new HashMap<>();
private final Set<Integer> validBlocking = new HashSet<>();
private final Set<Integer> knownHolograms = new HashSet<>();
@Getter
@Setter
private boolean blocking = false;
@Setter
private boolean autoTeam = false;
@Setter
private int entityID;
private boolean teamExists = false;
public EntityTracker(UserConnection user) {
super(user);
@ -51,8 +52,8 @@ public class EntityTracker extends StoredObject {
}
}
public void setSecondHand(UserConnection connection, Item item) {
PacketWrapper wrapper = new PacketWrapper(0x3C, null, connection);
public void setSecondHand(Item item) {
PacketWrapper wrapper = new PacketWrapper(0x3C, null, getUser());
wrapper.write(Type.VAR_INT, entityID);
wrapper.write(Type.VAR_INT, 1); // slot
wrapper.write(Type.ITEM, item);
@ -92,7 +93,7 @@ public class EntityTracker extends StoredObject {
if (type == EntityType.ENDER_DRAGON) {
if (metadata.getId() == 11) {
metadataList.remove(metadata);
// metadataList.add(new Metadata(11, NewType.Byte.getTypeID(), Type.VAR_INT, 0));
// metadataList.add(new Metadata(11, NewType.Byte.getTypeID(), Type.VAR_INT, 0));
}
}
@ -104,10 +105,10 @@ public class EntityTracker extends StoredObject {
if ((data & 0x10) == 0x10) {
if (validBlocking.contains(entityID)) {
Item shield = new Item((short) 442, (byte) 1, (short) 0, null);
setSecondHand(getUser(), shield);
setSecondHand(shield);
}
} else {
setSecondHand(getUser(), null);
setSecondHand(null);
}
}
}
@ -166,4 +167,34 @@ public class EntityTracker extends StoredObject {
}
}
}
public void sendTeamPacket(boolean b) {
PacketWrapper wrapper = new PacketWrapper(0x41, null, getUser());
wrapper.write(Type.STRING, "viaversion"); // Use viaversion as name
if (b) {
// add
if (!teamExists) {
wrapper.write(Type.BYTE, (byte) 0); // make team
wrapper.write(Type.STRING, "viaversion");
wrapper.write(Type.STRING, ""); // prefix
wrapper.write(Type.STRING, ""); // suffix
wrapper.write(Type.BYTE, (byte) 0); // friendly fire
wrapper.write(Type.STRING, ""); // nametags
wrapper.write(Type.STRING, "never"); // collision rule :)
wrapper.write(Type.BYTE, (byte) 0); // color
} else {
wrapper.write(Type.BYTE, (byte) 3);
}
wrapper.write(Type.VAR_INT, 1); // player count
wrapper.write(Type.STRING, getUser().get(ProtocolInfo.class).getUsername());
} else {
wrapper.write(Type.BYTE, (byte) 1); // remove team
}
teamExists = b;
try {
wrapper.send();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,16 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.storage;
import lombok.Getter;
import lombok.Setter;
import us.myles.ViaVersion2.api.data.StoredObject;
import us.myles.ViaVersion2.api.data.UserConnection;
@Getter
@Setter
public class InventoryTracker extends StoredObject {
private String inventory;
public InventoryTracker(UserConnection user) {
super(user);
}
}

View File

@ -46,7 +46,6 @@ public abstract class PacketRemapper {
for (Pair<ValueReader, ValueWriter> valueRemapper : valueRemappers) {
Object object = valueRemapper.getKey().read(packetWrapper);
// Convert object to write type :O!!!
// TODO: Data converter lol
valueRemapper.getValue().write(packetWrapper, object);
}
// If we had handlers we'd put them here

View File

@ -13,7 +13,6 @@ public class ItemType extends Type<Item> {
public Item read(ByteBuf buffer) throws Exception {
short id = buffer.readShort();
if (id < 0) {
System.out.println("null item");
return null;
} else {
Item item = new Item();
@ -21,7 +20,6 @@ public class ItemType extends Type<Item> {
item.setAmount(buffer.readByte());
item.setData(buffer.readShort());
item.setTag(Type.NBT.read(buffer));
System.out.println("item tag: " + item.getTag());
return item;
}
}
@ -30,7 +28,6 @@ public class ItemType extends Type<Item> {
public void write(ByteBuf buffer, Item object) throws Exception {
if (object == null) {
buffer.writeShort(-1);
System.out.println("writing -1");
} else {
buffer.writeShort(object.getId());
buffer.writeByte(object.getAmount());