de.paleocrafter.pmfw.tileentity.TileEntityWithData.java Source code

Java tutorial

Introduction

Here is the source code for de.paleocrafter.pmfw.tileentity.TileEntityWithData.java

Source

package de.paleocrafter.pmfw.tileentity;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.google.common.primitives.Primitives;

import cpw.mods.fml.common.network.PacketDispatcher;
import de.paleocrafter.pmfw.network.data.IDataObject;
import de.paleocrafter.pmfw.network.data.TileData;
import de.paleocrafter.pmfw.network.packet.TileDataPacket;

import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.packet.Packet;
import net.minecraft.tileentity.TileEntity;

/**
 * 
 * PaleoMachineFramework
 * 
 * TileEntityWithData
 * 
 * @author PaleoCrafter
 * @license Lesser GNU Public License v3 (http://www.gnu.org/licenses/lgpl.html)
 * 
 */
public class TileEntityWithData extends TileEntity {

    @Override
    public void writeToNBT(NBTTagCompound tag) {
        NBTTagCompound subFields = new NBTTagCompound("TileData");

        Class<?> clazz = this.getClass();
        int iteration = 0;
        do {
            NBTTagCompound clazzTag = new NBTTagCompound(String.valueOf(iteration));
            writeNBTFromClass(clazzTag, clazz);
            tag.setCompoundTag(String.valueOf(iteration), clazzTag);
            iteration++;
        } while ((clazz = clazz.getSuperclass()) != TileEntityWithData.class);
        tag.setInteger("TileDataCount", iteration - 1);

        tag.setCompoundTag("TileData", subFields);
    }

    @Override
    public void readFromNBT(NBTTagCompound tag) {
        NBTTagCompound subFields = tag.getCompoundTag("TileData");
        int dataCount = tag.getInteger("TileDataCount");
        for (int i = 0; i <= dataCount; i++) {
            Class<?> clazz = this.getClass();
            for (int j = 0; j < i; j++) {
                if (clazz != null)
                    clazz = clazz.getSuperclass();
            }

            readNBTToClass(subFields.getCompoundTag(String.valueOf(i)), clazz);
        }
    }

    private void writeNBTFromClass(NBTTagCompound tag, Class<?> clazz) {
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            Annotation anno = field.getAnnotation(TileData.class);
            if (anno != null) {
                if (((TileData) anno).storeToNBT()) {
                    try {
                        String className = null;
                        Class<?> primType = Primitives.wrap(field.getType());
                        Object value = field.get(this);
                        if (primType != null || value instanceof String || value instanceof IDataObject) {
                            Class<?> type = field.getType();
                            if (primType != null) {
                                type = primType;
                            }
                            className = type.getSimpleName();
                            className = Character.toUpperCase(className.charAt(0)) + className.substring(1);
                            if (className.equals("Character")) {
                                className = "String";
                                value = String.valueOf(value);
                            }
                            if (className != null) {
                                if (value instanceof IDataObject) {
                                    NBTTagList list = new NBTTagList(field.getName());
                                    ((IDataObject) value).writeToNBT(list);
                                    tag.setTag(field.getName(), list);
                                } else {
                                    Method method = tag.getClass().getMethod("set" + className, String.class,
                                            field.getType());
                                    method.invoke(tag, field.getName(), value);
                                }
                            }
                        }
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void readNBTToClass(NBTTagCompound tag, Class<?> clazz) {
        NBTBase[] subTags = (NBTBase[]) tag.getTags().toArray(new NBTBase[tag.getTags().size()]);
        for (NBTBase field : subTags) {
            try {
                Field classField = clazz.getDeclaredField(field.getName());
                classField.setAccessible(true);

                Annotation anno = classField.getAnnotation(TileData.class);

                if (anno != null && ((TileData) anno).storeToNBT()) {

                    String className = field.getClass().getSimpleName().replace("NBTTag", "");
                    Method method = tag.getClass().getMethod("get" + className);
                    if (classField.getType().isAssignableFrom(Character.class)) {
                        classField.set(this, (Character) method.invoke(tag, field.getName()));
                    } else if (field instanceof NBTTagList) {
                        try {
                            IDataObject obj = (IDataObject) classField.getType().newInstance();
                            obj.readFromNBT((NBTTagList) field);
                            classField.set(this, obj);
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        }
                    } else
                        classField.set(this, method.invoke(tag, field.getName()));
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

    public byte[] getPacketData() {
        ByteArrayDataOutput out = ByteStreams.newDataOutput();
        Class<?> clazz = this.getClass();
        int superClassCount = 0;
        while ((clazz = clazz.getSuperclass()) != TileEntityWithData.class) {
            superClassCount++;
        }

        out.writeInt(superClassCount);

        clazz = this.getClass();
        int iteration = 0;
        do {
            writePacketFromClass(out, clazz, iteration);
            iteration++;
        } while ((clazz = clazz.getSuperclass()) != TileEntityWithData.class);

        return out.toByteArray();
    }

    public void readFromPacket(ByteArrayDataInput in) {
        int superClassCount = in.readInt();
        for (int i = 0; i <= superClassCount; i++) {
            Class<?> clazz = this.getClass();
            for (int j = 0; j < i; j++) {
                if (clazz != null)
                    clazz = clazz.getSuperclass();
            }
            readPacketToClass(in, clazz, i);
        }
    }

    public void syncWithClient() {
        if (!worldObj.isRemote) {
            PacketDispatcher.sendPacketToAllAround(xCoord, yCoord, zCoord, 32, worldObj.provider.dimensionId,
                    getDescriptionPacket());
        }
    }

    private void writePacketFromClass(ByteArrayDataOutput out, Class<?> clazz, int iteration) {
        int fieldCount = 0;
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            Annotation anno = field.getAnnotation(TileData.class);
            if (anno != null)
                fieldCount++;
        }
        out.writeInt(fieldCount);
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            Annotation anno = field.getAnnotation(TileData.class);
            if (anno != null) {
                if (((TileData) anno).storeToPacket()) {
                    try {
                        String className = null;
                        className = field.getType().getSimpleName();
                        className = Character.toUpperCase(className.charAt(0)) + className.substring(1);
                        if (field.getType().isAssignableFrom(String.class))
                            className = "UTF";

                        if (className != null) {
                            Object value = field.get(this);
                            Class<?> type = field.getType();
                            if (Primitives.wrap(type) != null || value instanceof String
                                    || value instanceof IDataObject) {
                                if (value instanceof Byte || value.getClass() == byte.class) {
                                    type = int.class;
                                    value = (byte) value;
                                }
                                if (value instanceof IDataObject) {
                                    out.writeUTF(field.getName());
                                    ((IDataObject) value).writeToPacket(out);
                                } else {
                                    Method method = out.getClass().getMethod("write" + className, type);
                                    out.writeUTF(field.getName());
                                    method.setAccessible(true);
                                    method.invoke(out, value);
                                }
                            }
                        }

                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void readPacketToClass(ByteArrayDataInput in, Class<?> clazz, int iteration) {
        try {
            int fieldCount = in.readInt();
            for (int i = 0; i < fieldCount; i++) {
                try {
                    String fieldName = in.readUTF();
                    Field field = clazz.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    String className = field.getType().getSimpleName();
                    className = Character.toUpperCase(className.charAt(0)) + className.substring(1);
                    if (field.getType().isAssignableFrom(String.class))
                        className = "UTF";
                    if (className != null) {
                        if (IDataObject.class.isAssignableFrom(field.getType())) {
                            IDataObject data = (IDataObject) field.getType().newInstance();

                            data.readFromPacket(in);
                            field.set(this, data);
                        } else {
                            Method method = in.getClass().getMethod("read" + className);
                            method.setAccessible(true);
                            field.set(this, method.invoke(in));
                        }
                    }
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {

        }
    }

    @Override
    public Packet getDescriptionPacket() {
        TileDataPacket packet = new TileDataPacket(xCoord, yCoord, zCoord, getPacketData());
        return packet.makePacket();
    }
}