001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.server.data;
019
020import io.netty.buffer.ByteBuf;
021import io.netty.buffer.ByteBufInputStream;
022import net.tridentsdk.base.Substance;
023import net.tridentsdk.inventory.Item;
024import net.tridentsdk.meta.nbt.*;
025
026public class Slot implements Writable, NBTSerializable {
027    @NBTField(name = "id", type = TagType.SHORT)
028    protected volatile short id;
029    protected volatile Substance mat;
030
031    @NBTField(name = "Slot", type = TagType.BYTE)
032    protected volatile byte slot;
033    @NBTField(name = "Count", type = TagType.BYTE)
034    protected volatile byte quantity;
035    @NBTField(name = "Damage", type = TagType.SHORT)
036    protected volatile short damageValue;
037    @NBTField(name = "tag", type = TagType.COMPOUND)
038    protected volatile CompoundTag compoundTag;
039
040    public Slot(ByteBuf buf) {
041        try {
042            this.id = buf.readShort();
043
044            this.mat = Substance.fromId(this.id);
045
046            if(this.id == -1) {
047                return;
048            }
049
050            this.quantity = (byte) buf.readUnsignedByte();
051            this.damageValue = buf.readShort();
052            byte b;
053
054            if((b = buf.readByte()) != 0) {
055                try {
056                    NBTDecoder builder = new NBTDecoder(new ByteBufInputStream(buf));
057
058                    this.compoundTag = builder.decode(b);
059                } catch(NBTException ignored) {
060                    // do something
061                }
062            }
063        } catch(Exception ignored) { // TODO Find out why this throws exceptions
064        }
065    }
066
067    public Slot(Item is) {
068        if (is == null) {
069            this.id = -1;
070            return;
071        }
072        this.id = (short) is.id();
073        this.mat = is.type();
074
075        this.quantity = (byte) is.quantity();
076        this.damageValue = (byte) is.damageValue();
077
078        // TODO: build NBT data
079    }
080
081    protected Slot() {
082    }
083
084    /**
085     * Gets the ID of the current item in the slot
086     *
087     * @return the item ID occupying the slot
088     */
089    public int id() {
090        return this.id;
091    }
092
093    /**
094     * Gets the type of the current item in the slot
095     *
096     * @return the item type occupying the slot
097     */
098    public Substance type() {
099        return this.mat;
100    }
101
102    /**
103     * Gets the amount of the current item in the slot
104     *
105     * @return the amount of the item occupying the slot
106     */
107    public short quantity() {
108        return this.quantity;
109    }
110
111    /**
112     * Gets the damage of the current item in the slot
113     *
114     * @return the damage of the item occupying the slot
115     */
116    public short damageValue() {
117        return this.damageValue;
118    }
119
120    /**
121     * Gets the NBT data of the current item in the slot
122     *
123     * @return the item NBT occupying the slot
124     */
125    public CompoundTag compoundTag() {
126        return this.compoundTag;
127    }
128
129    public byte slot() {
130        return slot;
131    }
132
133    @Override
134    public void write(ByteBuf buf) {
135        if(id <= 0) {
136            buf.writeShort(-1);
137            return;
138        } else {
139            buf.writeShort(id);
140        }
141
142        buf.writeByte((int) this.quantity);
143        buf.writeShort((int) this.damageValue);
144
145        if (this.compoundTag != null) {
146            // TODO: toPacket compound tag
147        } else {
148            buf.writeByte(0); // No NBT
149        }
150    }
151
152    public Item item() {
153        Item is = new Item(mat);
154
155        is.setQuantity(quantity);
156        is.setDamageValue(damageValue);
157
158        // TODO: transfer over item meta
159
160        return is;
161    }
162}