Package me.taylorkelly.bigbrother.datablock

Source Code of me.taylorkelly.bigbrother.datablock.DeltaChest$DeltaEntry

package me.taylorkelly.bigbrother.datablock;

import me.taylorkelly.bigbrother.BBLogging;
import me.taylorkelly.bigbrother.BBPlayerInfo;

import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.Chest;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;

import com.sk89q.worldedit.blocks.ItemType;

public class DeltaChest extends BBDataBlock {

    public enum DeltaType {
        NO_CHANGE,
        ADDED,
        REMOVED,
        REPLACED
    }

    /*public DeltaChest(String player, Chest chest, String changes) {
        super(player, Action.DELTA_CHEST, chest.getWorld().getName(), chest.getX(), chest.getY(), chest.getZ(), chest.getTypeId(), changes);
    }*/

    private DeltaChest(BBPlayerInfo player, String world, int x, int y, int z, int type, String data) {
        super(player, Action.DELTA_CHEST, world, x, y, z, type, data);
    }
   
    public DeltaChest(String player, Chest chest, ItemStack[] orig, ItemStack[] latest) {
        super(player, Action.DELTA_CHEST, chest.getWorld().getName(), chest.getX(), chest.getY(), chest.getZ(), chest.getTypeId(),
        DeltaChest.getInventoryDelta(orig, latest));
    }

    // NEW FORMAT TO SUPPORT DAMAGE TRACKING (Wool, etc)
    // {SLOT:ID:[+|-]COUNT:DATA:DAMAGE[;...]
    // 0:1:15:20:0;
    // + = Added stuff
    // - = Removed stuff
    // no symbol = Replaced a slot
    public static String getInventoryDelta(ItemStack[] orig, ItemStack[] latest) {
        StringBuilder builder = new StringBuilder();
        builder.append("{"); // Marker for the new format
        for (int i = 0; i < orig.length; i++) {
            DeltaEntry e = new DeltaEntry(i,orig[i],latest[i]);
            builder.append(e.toString());
            if (i + 1 < orig.length) {
                builder.append(";");
            }
        }
        return builder.toString();
    }
   
    public static DeltaEntry[] processDeltaStream(int chestCapacity,String data) {
        data=data.substring(1);
        DeltaEntry[] de = new DeltaEntry[chestCapacity];
        for(int i = 0;i<chestCapacity;i++) {
            de[i] = new DeltaEntry(i);
        }
        for(String chunk : data.split(";")) {
            DeltaEntry e = new DeltaEntry(chunk);
            de[e.Slot]=e;
        }
        return de;
    }
    public static class DeltaEntry {
        public int Slot;
        public int ID=0;
        public int Amount=0;
        public short Damage=0;
        public byte Data=0;
        public DeltaType Type=DeltaType.NO_CHANGE;
        private ItemStack newStack;
        private ItemStack oldStack;
       
        public DeltaEntry(int slot) {
            Slot=slot;
        }
        public DeltaEntry(String chunk) {
            String[] dchunks=chunk.split(":");
            Slot=Integer.valueOf(dchunks[0]);
            if(chunk.contains("=")) {
                String[] schunks = chunk.split("=");
                oldStack=parseStack(1,schunks[0].split(":"));
                newStack=parseStack(0,schunks[1].split(":"));
                ID=newStack.getTypeId();
                Type=DeltaType.REPLACED;
                Amount=newStack.getAmount();
                Damage=newStack.getDurability();
                Data=newStack.getData().getData();
            } else {
                ID=Integer.valueOf(dchunks[1]);
                if(dchunks[2].startsWith("+")) {
                    dchunks[2]=dchunks[2].substring(1);
                    Type=DeltaType.ADDED;
                } else {
                    if(dchunks[2].startsWith("-"))
                        Type=DeltaType.REMOVED;
                }
                Amount=Integer.valueOf(dchunks[2]);
                Damage=Short.valueOf(dchunks[3]);
                Data=Byte.valueOf(dchunks[4]);
            }
        }
       
        private ItemStack parseStack(int i, String[] dchunks) {
            ItemStack stack=new ItemStack(Integer.valueOf(dchunks[i]));
            stack.setAmount(Integer.valueOf(dchunks[i++]));
            stack.setDurability(Short.valueOf(dchunks[i++]));
            stack.setData(new MaterialData(Byte.valueOf(dchunks[i++])));
            return stack;
        }
       
        public DeltaEntry(int slot, ItemStack orig, ItemStack latest) {
            oldStack=orig;
            newStack=latest;
            Slot=slot;
            orig=fixStack(orig);
            latest=fixStack(latest);
           
            if(isTypeDifferent(orig,latest)) {
                Type=DeltaType.REPLACED;
                ID=latest.getTypeId();
                Amount=latest.getAmount();
                Damage=latest.getDurability();
                // Why do you do this
                if(orig.getData()==null)
                    Data=0;
                else
                    Data=orig.getData().getData();
            } else {
                ID=orig.getTypeId();
                Damage=orig.getDurability();
                // Why do you do this
                if(orig.getData()==null)
                    Data=0;
                else
                    Data=orig.getData().getData();
                Amount=orig.getAmount()-latest.getAmount();
                if(Amount==0)
                    Type=DeltaType.NO_CHANGE;
                else if(Amount>0)
                    Type=DeltaType.REMOVED;
                else if(Amount<0)
                    Type=DeltaType.ADDED;
            }
        }

        private boolean isTypeDifferent(ItemStack orig, ItemStack latest) {
            if(orig.getTypeId()==0 || latest.getTypeId()==0)
                return false;
           
            if(!orig.getType().equals(latest.getType()))
                return true;
            else {
                return(ItemType.usesDamageValue(orig.getTypeId()) && orig.getDurability()!=latest.getDurability());
            }
        }

        private ItemStack fixStack(ItemStack stack) {
            if(stack==null) {
                stack = new ItemStack(0);
                stack.setData(new MaterialData(0));
            }
           
            // If air, data, durability, and damage are always 0.
            if(stack.getType().equals(Material.AIR))
            {
                stack.setAmount(0);
                stack.setData(new MaterialData(0));
                stack.setDurability((byte)0);
            }
            return stack;
        }
       
        @Override
        public String toString() {
            // {SLOT:ID:[+|-]COUNT:DATA:DAMAGE[;...]
            // SLOT:ID:COUNT:DATA:DAMAGE=NEWID:NEWCOUNT...
            if(Type.equals(DeltaType.REPLACED)) {
                return Slot+":"+rawDump(oldStack)+"="+rawDump(newStack);
            } else {
                StringBuilder b = new StringBuilder();
                b.append(Slot);
                b.append(":");
                b.append(ID);
                b.append(":");
                switch(Type) {
                case ADDED:
                    b.append("+");
                    break;
                case REMOVED:
                    b.append("-");
                break;
                default:
                    break;
                }
                b.append((Amount==-1) ? 0 : Amount);
                b.append(":");
                b.append(Data);
                b.append(":");
                b.append(Damage);
                return b.toString();
            }
        }
       
        private String rawDump(ItemStack a) {
            // ID:COUNT:DATA:DAMAGE
            StringBuilder b = new StringBuilder();
            b.append(a.getTypeId());
            b.append(":");
            b.append(a.getAmount());
            b.append(":");
            byte dat;
            // Why do you do this
            if(a.getData()==null)
                dat=0;
            else
                dat=a.getData().getData();
            b.append(dat);
            b.append(":");
            b.append(a.getDurability());
            return b.toString();
        }
    }

    @Override
    public void rollback(World wld) {
        World currWorld = wld;
        if (!currWorld.isChunkLoaded(x >> 4, z >> 4)) {
            currWorld.loadChunk(x >> 4, z >> 4);
        }
        Block block = currWorld.getBlockAt(x, y, z);
        if(data.startsWith("{")) { // Check for new marker!
            do_NewRollback(currWorld,block);
        } else {
            do_OldRollback(currWorld,block);
        }
    }
    private void do_NewRollback(World currWorld, Block block) {
        if (block.getState() instanceof Chest) {
            Chest chest = (Chest) block.getState();
            DeltaEntry[] diff = processDeltaStream(chest.getInventory().getSize(),data);
            Inventory inv = chest.getInventory();
            for(int i = 0;i<chest.getInventory().getSize();i++) {
                switch(diff[i].Type) {
                case ADDED:
                case REMOVED:
                    ItemStack stack = inv.getItem(i);
                    stack.setAmount(stack.getAmount()-diff[i].Amount);
                    stack.setDurability(diff[i].Damage);
                    inv.setItem(i, stack);
                    break;
                case REPLACED:
                    inv.setItem(i, diff[i].oldStack);
                    break;
                case NO_CHANGE:
                    break;
                }
            }
        }
    }

    public void do_OldRollback(World currWorld,Block block) {
        String[] changes = data.split(";");
        if (block.getState() instanceof Chest) {
            Chest chest = (Chest) block.getState();
            Inventory inv = chest.getInventory();
            for (int i = 0; i < changes.length; i++) {
                String change = changes[i];
                try {
                    if (change.equals("")) {
                        continue;
                    }
                    String[] pieces = change.split(",");
                    if (pieces.length != 2) {
                        continue;
                    }
                    int id = 0;
                    int itemData = 0;
                    if (pieces[0].contains(":")) {
                        String[] subPieces = pieces[0].split(":");
                        id = Integer.parseInt(subPieces[0]);
                        itemData = Integer.parseInt(subPieces[1]);
                    } else {
                        id = Integer.parseInt(pieces[0]);
                    }
                    int amount = -1 * Integer.parseInt(pieces[1]);
                    ItemStack stack = inv.getItem(i);
                    if (stack == null || stack.getAmount() == 0) {
                        if (amount > 0) {
                            ItemStack newStack = new ItemStack(id, amount, (byte) 0x01, (byte) itemData);
                            inv.setItem(i, newStack);
                        } else {
                            BBLogging.warning("Chest restore conflict. Trying to remove from a empty slot");
                        }
                    } else {
                        if (stack.getTypeId() != id) {
                            BBLogging.warning("Chest restore conflict. Different types.");
                        } else {
                            amount = stack.getAmount() + amount;
                            int damage = stack.getDurability();
                            if (amount < 0) {
                                inv.clear(i);
                            } else {
                                ItemStack newStack = new ItemStack(id, amount, (byte) damage, (byte) itemData);
                                inv.setItem(i, newStack);
                            }
                        }
                    }
                } catch (NumberFormatException e) {
                    BBLogging.warning("Broken Chest Log with piece: " + change);
                }
            }
        } else {
            BBLogging.warning("Error when restoring chest");
        }
    }

    @Override
    public void redo(Server server) {
        World currWorld = server.getWorld(world);
        if (!currWorld.isChunkLoaded(x >> 4, z >> 4)) {
            currWorld.loadChunk(x >> 4, z >> 4);
        }

        String[] changes = data.split(";");
        Block block = currWorld.getBlockAt(x, y, z);
        if (block.getState() instanceof Chest) {
            Chest chest = (Chest) block.getState();
            Inventory inv = chest.getInventory();
            for (int i = 0; i < changes.length; i++) {
                String change = changes[i];
                try {
                    if (change.equals("")) {
                        continue;
                    }
                    String[] pieces = change.split(",");
                    if (pieces.length != 2) {
                        continue;
                    }
                    int id = 0;
                    int itemData = 0;
                    if (pieces[0].contains(":")) {
                        String[] subPieces = pieces[0].split(":");
                        id = Integer.parseInt(subPieces[0]);
                        itemData = Integer.parseInt(subPieces[1]);
                    } else {
                        id = Integer.parseInt(pieces[0]);
                    }
                    int amount = Integer.parseInt(pieces[1]);
                    ItemStack stack = inv.getItem(i);
                    if (stack == null || stack.getAmount() == 0) {
                        if (amount > 0) {
                            ItemStack newStack = new ItemStack(id, amount, (byte) 0x01, (byte) itemData);
                            inv.setItem(i, newStack);
                        } else {
                            BBLogging.warning("Chest restore conflict. Trying to remove from a empty slot");
                        }
                    } else {
                        if (stack.getTypeId() != id) {
                            BBLogging.warning("Chest restore conflict. Different types.");
                        } else {
                            amount = stack.getAmount() + amount;
                            int damage = stack.getDurability();
                            if (amount < 0) {
                                inv.clear(i);
                            } else {
                                ItemStack newStack = new ItemStack(id, amount, (byte) damage, (byte) itemData);
                                inv.setItem(i, newStack);
                            }
                        }
                    }
                } catch (NumberFormatException e) {
                    BBLogging.warning("Broken Chest Log with piece: " + change);
                }
            }
        } else {
            BBLogging.warning("Error when restoring chest");
        }
    }

    public static BBDataBlock getBBDataBlock(BBPlayerInfo pi, String world, int x, int y, int z, int type, String data) {
        return new DeltaChest(pi, world, x, y, z, type, data);
    }
}
TOP

Related Classes of me.taylorkelly.bigbrother.datablock.DeltaChest$DeltaEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.