Polymorph classes supported in serializer.
The serializer now supports cases where the actual object is different from the object declared, sending once the class name on the stream.
This commit is contained in:
parent
08d01c0394
commit
3cf761226e
7 changed files with 196 additions and 78 deletions
|
@ -13,10 +13,12 @@ import buildcraft.api.core.LaserKind;
|
||||||
import buildcraft.builders.blueprints.Blueprint;
|
import buildcraft.builders.blueprints.Blueprint;
|
||||||
import buildcraft.builders.blueprints.BlueprintDatabase;
|
import buildcraft.builders.blueprints.BlueprintDatabase;
|
||||||
import buildcraft.core.Box;
|
import buildcraft.core.Box;
|
||||||
|
import buildcraft.core.DefaultProps;
|
||||||
import buildcraft.core.TileBuildCraft;
|
import buildcraft.core.TileBuildCraft;
|
||||||
import buildcraft.core.network.PacketUpdate;
|
import buildcraft.core.network.PacketUpdate;
|
||||||
import buildcraft.core.network.NetworkData;
|
import buildcraft.core.network.NetworkData;
|
||||||
import buildcraft.core.network.RPC;
|
import buildcraft.core.network.RPC;
|
||||||
|
import buildcraft.core.network.RPCHandler;
|
||||||
import buildcraft.core.network.RPCSide;
|
import buildcraft.core.network.RPCSide;
|
||||||
import buildcraft.core.proxy.CoreProxy;
|
import buildcraft.core.proxy.CoreProxy;
|
||||||
import buildcraft.core.utils.Utils;
|
import buildcraft.core.utils.Utils;
|
||||||
|
@ -144,7 +146,7 @@ public class TileArchitect extends TileBuildCraft implements IInventory {
|
||||||
return blueprint;
|
return blueprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RPC
|
@RPC (RPCSide.SERVER)
|
||||||
public void handleClientInput(char c) {
|
public void handleClientInput(char c) {
|
||||||
if (c == 8) {
|
if (c == 8) {
|
||||||
if (name.length() > 0) {
|
if (name.length() > 0) {
|
||||||
|
@ -155,7 +157,13 @@ public class TileArchitect extends TileBuildCraft implements IInventory {
|
||||||
name += c;
|
name += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendNetworkUpdate();
|
|
||||||
|
RPCHandler.rpcBroadcastPlayers(this, "setName", DefaultProps.NETWORK_UPDATE_RANGE, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RPC
|
||||||
|
public void setName (String name) {
|
||||||
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package buildcraft.builders;
|
package buildcraft.builders;
|
||||||
|
|
||||||
import buildcraft.BuildCraftBuilders;
|
import buildcraft.BuildCraftBuilders;
|
||||||
|
import buildcraft.builders.blueprints.BlueprintDatabase;
|
||||||
import buildcraft.builders.blueprints.BlueprintMeta;
|
import buildcraft.builders.blueprints.BlueprintMeta;
|
||||||
import buildcraft.core.TileBuildCraft;
|
import buildcraft.core.TileBuildCraft;
|
||||||
import buildcraft.core.blueprints.BptBase;
|
import buildcraft.core.blueprints.BptBase;
|
||||||
|
@ -10,21 +11,15 @@ import buildcraft.core.network.RPC;
|
||||||
import buildcraft.core.network.RPCHandler;
|
import buildcraft.core.network.RPCHandler;
|
||||||
import buildcraft.core.network.RPCMessageInfo;
|
import buildcraft.core.network.RPCMessageInfo;
|
||||||
import buildcraft.core.network.RPCSide;
|
import buildcraft.core.network.RPCSide;
|
||||||
import buildcraft.core.network.NetworkData;
|
|
||||||
import buildcraft.core.proxy.CoreProxy;
|
import buildcraft.core.proxy.CoreProxy;
|
||||||
import buildcraft.core.utils.Utils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import com.google.common.io.ByteStreams;
|
|
||||||
|
|
||||||
import cpw.mods.fml.relauncher.Side;
|
import cpw.mods.fml.relauncher.Side;
|
||||||
import cpw.mods.fml.relauncher.SideOnly;
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
import paulscode.sound.Library;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.inventory.IInventory;
|
import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -105,20 +100,20 @@ public class TileBlueprintLibrary extends TileBuildCraft implements IInventory {
|
||||||
@SideOnly (Side.CLIENT)
|
@SideOnly (Side.CLIENT)
|
||||||
public void updateCurrentNames() {
|
public void updateCurrentNames() {
|
||||||
currentBlueprint.clear();
|
currentBlueprint.clear();
|
||||||
RPCHandler.rpcServer(this, "fetchPage", 1);
|
RPCHandler.rpcServer(this, "fetchPage", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RPC (RPCSide.SERVER)
|
@RPC (RPCSide.SERVER)
|
||||||
public void fetchPage (int pageId, RPCMessageInfo info) {
|
public void fetchPage (int pageId, RPCMessageInfo info) {
|
||||||
for (int i = 0; i < BuildCraftBuilders.LIBRARY_PAGE_SIZE; ++i) {
|
List <BlueprintMeta> metas = BlueprintDatabase.getPage(pageId, 12);
|
||||||
BlueprintMeta dummyMeta = new BlueprintMeta ();
|
|
||||||
dummyMeta.name = "Blueprint #" + i;
|
|
||||||
|
|
||||||
RPCHandler.rpcPlayer(this, "receiveBlueprintMeta", info.sender, dummyMeta);
|
for (BlueprintMeta meta : metas) {
|
||||||
|
RPCHandler.rpcPlayer(this, "receiveBlueprintMeta", info.sender, meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RPC (RPCSide.CLIENT)
|
@RPC (RPCSide.CLIENT)
|
||||||
|
// TODO: It would be more efficient to get directly a list or an array here
|
||||||
public void receiveBlueprintMeta (BlueprintMeta meta) {
|
public void receiveBlueprintMeta (BlueprintMeta meta) {
|
||||||
currentBlueprint.add(meta.name);
|
currentBlueprint.add(meta.name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,7 @@ public class Blueprint {
|
||||||
@NetworkData
|
@NetworkData
|
||||||
public BlueprintMeta meta;
|
public BlueprintMeta meta;
|
||||||
|
|
||||||
// TODO: may need additional support from the serialization system:
|
@NetworkData
|
||||||
// Schematic is an abstract class, the actual objects to serialize
|
|
||||||
// are sub classes
|
|
||||||
private final Schematic[][][] schematics;
|
private final Schematic[][][] schematics;
|
||||||
|
|
||||||
@NetworkData
|
@NetworkData
|
||||||
|
|
|
@ -19,7 +19,10 @@ import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
@ -40,7 +43,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||||
public class BlueprintDatabase {
|
public class BlueprintDatabase {
|
||||||
/**
|
/**
|
||||||
* Initialize the blueprint database.
|
* Initialize the blueprint database.
|
||||||
*
|
*
|
||||||
* @param configDir config directory to read the blueprints from.
|
* @param configDir config directory to read the blueprints from.
|
||||||
*/
|
*/
|
||||||
public static void init(File configDir) {
|
public static void init(File configDir) {
|
||||||
|
@ -56,18 +59,47 @@ public class BlueprintDatabase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list with the metadata for all available blueprints.
|
* Get a list with the metadata for all available blueprints.
|
||||||
*
|
*
|
||||||
* @return meta data iterable
|
* @return meta data iterable
|
||||||
*/
|
*/
|
||||||
public static Iterable<BlueprintMeta> getList() {
|
public static Iterable<BlueprintMeta> getList() {
|
||||||
return blueprintMetas.values();
|
return blueprintMetas.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of blueprint on a given page.
|
||||||
|
*
|
||||||
|
* FIXME: This returns blueprints in no particular order. We probably want
|
||||||
|
* to have an ordered list of blueprint instead
|
||||||
|
*/
|
||||||
|
public static List <BlueprintMeta> getPage (int pageId, int pageSize) {
|
||||||
|
List <BlueprintMeta> result = new ArrayList<BlueprintMeta>();
|
||||||
|
|
||||||
|
int start = pageId * pageSize;
|
||||||
|
int stop = (pageId + 1) * pageSize;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (BlueprintMeta meta : blueprintMetas.values()) {
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i >= stop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= start) {
|
||||||
|
result.add (meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a specific blueprint by id.
|
* Get a specific blueprint by id.
|
||||||
*
|
*
|
||||||
* @note The blueprint will be loaded as needed.
|
* @note The blueprint will be loaded as needed.
|
||||||
*
|
*
|
||||||
* @param id blueprint id
|
* @param id blueprint id
|
||||||
* @return blueprint or null if it can't be retrieved
|
* @return blueprint or null if it can't be retrieved
|
||||||
*/
|
*/
|
||||||
|
@ -86,7 +118,7 @@ public class BlueprintDatabase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a blueprint to the database and save it to disk.
|
* Add a blueprint to the database and save it to disk.
|
||||||
*
|
*
|
||||||
* @param blueprint blueprint to add
|
* @param blueprint blueprint to add
|
||||||
* @return id for the added blueprint
|
* @return id for the added blueprint
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
|
|
||||||
package buildcraft.core.network;
|
package buildcraft.core.network;
|
||||||
|
|
||||||
import buildcraft.BuildCraftCore;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
@ -58,6 +57,12 @@ import java.util.TreeMap;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ClassMapping {
|
public class ClassMapping {
|
||||||
|
|
||||||
|
private class SerializationContext {
|
||||||
|
public ArrayList<ClassMapping> idToClass = new ArrayList<ClassMapping> ();
|
||||||
|
public Map <String, Integer> classToId = new TreeMap<String, Integer> ();
|
||||||
|
}
|
||||||
|
|
||||||
private LinkedList<Field> floatFields = new LinkedList<Field>();
|
private LinkedList<Field> floatFields = new LinkedList<Field>();
|
||||||
private LinkedList<Field> doubleFields = new LinkedList<Field>();
|
private LinkedList<Field> doubleFields = new LinkedList<Field>();
|
||||||
private LinkedList<Field> stringFields = new LinkedList<Field>();
|
private LinkedList<Field> stringFields = new LinkedList<Field>();
|
||||||
|
@ -65,11 +70,15 @@ public class ClassMapping {
|
||||||
private LinkedList<Field> intFields = new LinkedList<Field>();
|
private LinkedList<Field> intFields = new LinkedList<Field>();
|
||||||
private LinkedList<Field> booleanFields = new LinkedList<Field>();
|
private LinkedList<Field> booleanFields = new LinkedList<Field>();
|
||||||
private LinkedList<Field> enumFields = new LinkedList<Field>();
|
private LinkedList<Field> enumFields = new LinkedList<Field>();
|
||||||
private LinkedList<ClassMapping> objectFields = new LinkedList<ClassMapping>();
|
|
||||||
|
|
||||||
private Field field;
|
class FieldObject {
|
||||||
|
public Field field;
|
||||||
|
public ClassMapping mapping;
|
||||||
|
}
|
||||||
|
|
||||||
private Class<? extends Object> clas;
|
private LinkedList<FieldObject> objectFields = new LinkedList<FieldObject>();
|
||||||
|
|
||||||
|
private Class<? extends Object> mappedClass;
|
||||||
|
|
||||||
enum CptType {
|
enum CptType {
|
||||||
Byte,
|
Byte,
|
||||||
|
@ -98,7 +107,7 @@ public class ClassMapping {
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public void analyzeClass(final Class<? extends Object> c) {
|
public void analyzeClass(final Class<? extends Object> c) {
|
||||||
try {
|
try {
|
||||||
clas = c;
|
mappedClass = c;
|
||||||
|
|
||||||
if (c.isArray()) {
|
if (c.isArray()) {
|
||||||
Class cptClass = c.getComponentType();
|
Class cptClass = c.getComponentType();
|
||||||
|
@ -149,13 +158,11 @@ public class ClassMapping {
|
||||||
} else if (fieldClass.equals(double.class)) {
|
} else if (fieldClass.equals(double.class)) {
|
||||||
doubleFields.add(f);
|
doubleFields.add(f);
|
||||||
} else {
|
} else {
|
||||||
// ADD SOME SAFETY HERE - if we're not child of
|
FieldObject obj = new FieldObject();
|
||||||
// Object
|
obj.mapping = get (fieldClass);
|
||||||
|
obj.field = f;
|
||||||
|
|
||||||
ClassMapping mapping = new ClassMapping(fieldClass);
|
objectFields.add(obj);
|
||||||
mapping.field = f;
|
|
||||||
|
|
||||||
objectFields.add(mapping);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,17 +179,25 @@ public class ClassMapping {
|
||||||
return updateAnnotation != null;
|
return updateAnnotation != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setData(Object obj, DataOutputStream data) throws IllegalArgumentException,
|
public void setData(Object obj, DataOutputStream data) throws IllegalArgumentException,
|
||||||
IllegalAccessException, IOException {
|
IllegalAccessException, IOException {
|
||||||
if (clas.isArray()) {
|
SerializationContext context = new SerializationContext();
|
||||||
setDataArray(obj, data);
|
|
||||||
|
setDataInt(obj, data, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataInt(Object obj, DataOutputStream data, SerializationContext context) throws IllegalArgumentException,
|
||||||
|
IllegalAccessException, IOException {
|
||||||
|
if (mappedClass.isArray()) {
|
||||||
|
setDataArray(obj, data, context);
|
||||||
} else {
|
} else {
|
||||||
setDataClass(obj, data);
|
setDataClass(obj, data, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
private void setDataClass(Object obj, DataOutputStream data) throws IllegalArgumentException,
|
private void setDataClass(Object obj, DataOutputStream data, SerializationContext context) throws IllegalArgumentException,
|
||||||
IllegalAccessException, IOException {
|
IllegalAccessException, IOException {
|
||||||
|
|
||||||
for (Field f : shortFields) {
|
for (Field f : shortFields) {
|
||||||
|
@ -220,21 +235,42 @@ public class ClassMapping {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ClassMapping c : objectFields) {
|
for (FieldObject f : objectFields) {
|
||||||
Object cpt = c.field.get(obj);
|
Object cpt = f.field.get(obj);
|
||||||
|
ClassMapping mapping = f.mapping;
|
||||||
|
|
||||||
if (cpt == null) {
|
if (cpt == null) {
|
||||||
data.writeBoolean(false);
|
data.writeBoolean(false);
|
||||||
} else {
|
} else {
|
||||||
|
Class realClass = cpt.getClass();
|
||||||
|
|
||||||
data.writeBoolean(true);
|
data.writeBoolean(true);
|
||||||
c.setData(cpt, data);
|
|
||||||
|
if (realClass.equals(f.mapping.mappedClass)) {
|
||||||
|
data.writeByte(0);
|
||||||
|
} else {
|
||||||
|
if (context.classToId.containsKey(realClass.getCanonicalName())) {
|
||||||
|
int index = context.classToId.get(realClass.getCanonicalName());
|
||||||
|
data.writeByte(index);
|
||||||
|
mapping = context.idToClass.get(index);
|
||||||
|
} else {
|
||||||
|
int index = context.classToId.size() + 1;
|
||||||
|
data.writeByte(index);
|
||||||
|
data.writeUTF(realClass.getCanonicalName());
|
||||||
|
context.classToId.put(realClass.getCanonicalName(), context.classToId.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping = get (realClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping.setDataInt(cpt, data, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDataArray(Object obj, DataOutputStream data) throws IllegalArgumentException,
|
private void setDataArray(Object obj, DataOutputStream data, SerializationContext context) throws IllegalArgumentException,
|
||||||
IllegalAccessException, IOException {
|
IllegalAccessException, IOException {
|
||||||
Class<? extends Object> cpt = clas.getComponentType();
|
Class<? extends Object> cpt = mappedClass.getComponentType();
|
||||||
|
|
||||||
switch (cptType) {
|
switch (cptType) {
|
||||||
case Byte: {
|
case Byte: {
|
||||||
|
@ -321,7 +357,7 @@ public class ClassMapping {
|
||||||
data.writeBoolean(false);
|
data.writeBoolean(false);
|
||||||
} else {
|
} else {
|
||||||
data.writeBoolean(true);
|
data.writeBoolean(true);
|
||||||
cptMapping.setData(arr [i], data);
|
cptMapping.setDataInt(arr [i], data, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,26 +398,35 @@ public class ClassMapping {
|
||||||
*
|
*
|
||||||
* WARNINGS
|
* WARNINGS
|
||||||
*
|
*
|
||||||
* - class instantiation will be done after the field type, not
|
* - only public non-final fields can be serialized
|
||||||
* the actual type used in serialization. Generally speaking, this system
|
* - non static nested classes are not supported
|
||||||
* is not robust to polymorphism
|
* - no reference analysis is done, e.g. an object referenced twice will
|
||||||
* - only public non-final fields can be serialized
|
* be serialized twice
|
||||||
|
*
|
||||||
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
public Object updateFromData(Object obj, DataInputStream data) throws IllegalArgumentException,
|
public Object updateFromData (Object obj, DataInputStream data) throws IllegalArgumentException,
|
||||||
IllegalAccessException, IOException, InstantiationException {
|
IllegalAccessException, IOException, InstantiationException, ClassNotFoundException {
|
||||||
if (clas.isArray()) {
|
SerializationContext context = new SerializationContext();
|
||||||
return updateFromDataArray(obj, data);
|
|
||||||
|
return updateFromDataInt(obj, data, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object updateFromDataInt (Object obj, DataInputStream data, SerializationContext context) throws IllegalArgumentException,
|
||||||
|
IllegalAccessException, IOException, InstantiationException, ClassNotFoundException {
|
||||||
|
if (mappedClass.isArray()) {
|
||||||
|
return updateFromDataArray(obj, data, context);
|
||||||
} else {
|
} else {
|
||||||
return updateFromDataClass(obj, data);
|
return updateFromDataClass(obj, data, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public Object updateFromDataClass(Object obj, DataInputStream data) throws IllegalArgumentException,
|
public Object updateFromDataClass(Object obj, DataInputStream data, SerializationContext context) throws IllegalArgumentException,
|
||||||
IllegalAccessException, IOException, InstantiationException {
|
IllegalAccessException, IOException, InstantiationException, ClassNotFoundException {
|
||||||
|
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
obj = clas.newInstance();
|
obj = mappedClass.newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Field f : shortFields) {
|
for (Field f : shortFields) {
|
||||||
|
@ -416,20 +461,48 @@ public class ClassMapping {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ClassMapping c : objectFields) {
|
// The data layout for an object is the following:
|
||||||
|
// [boolean] does the object exist (e.g. non-null)
|
||||||
|
// {false} exit
|
||||||
|
// [int] what is the object real class?
|
||||||
|
// {0} the same as the declared class
|
||||||
|
// {1-x} a different one
|
||||||
|
// [string] if the number is not yet registered, the name of the
|
||||||
|
// class
|
||||||
|
// [bytes] the actual contents
|
||||||
|
|
||||||
|
for (FieldObject f : objectFields) {
|
||||||
if (data.readBoolean()) {
|
if (data.readBoolean()) {
|
||||||
c.field.set (obj, c.updateFromData(c.field.get(obj), data));
|
ClassMapping mapping = f.mapping;
|
||||||
|
|
||||||
|
int index = data.readByte();
|
||||||
|
|
||||||
|
if (index != 0) {
|
||||||
|
if (context.idToClass.size() < index) {
|
||||||
|
String className = data.readUTF();
|
||||||
|
|
||||||
|
Class cls = Class.forName(className);
|
||||||
|
|
||||||
|
mapping = get (cls);
|
||||||
|
|
||||||
|
context.idToClass.add(get (cls));
|
||||||
|
} else {
|
||||||
|
mapping = context.idToClass.get(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f.field.set (obj, mapping.updateFromDataInt(f.field.get(obj), data, context));
|
||||||
} else {
|
} else {
|
||||||
c.field.set(obj, null);
|
f.field.set(obj, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object updateFromDataArray(Object obj, DataInputStream data) throws IllegalArgumentException,
|
private Object updateFromDataArray(Object obj, DataInputStream data, SerializationContext context) throws IllegalArgumentException,
|
||||||
IllegalAccessException, IOException, InstantiationException {
|
IllegalAccessException, IOException, InstantiationException, ClassNotFoundException {
|
||||||
Class<? extends Object> cpt = clas.getComponentType();
|
Class<? extends Object> cpt = mappedClass.getComponentType();
|
||||||
|
|
||||||
int size = data.readInt();
|
int size = data.readInt();
|
||||||
|
|
||||||
|
@ -568,7 +641,7 @@ public class ClassMapping {
|
||||||
|
|
||||||
for (int i = 0; i < arr.length; ++i) {
|
for (int i = 0; i < arr.length; ++i) {
|
||||||
if (data.readBoolean()) {
|
if (data.readBoolean()) {
|
||||||
arr [i] = cptMapping.updateFromData(arr [i], data);
|
arr [i] = cptMapping.updateFromDataInt(arr [i], data, context);
|
||||||
} else {
|
} else {
|
||||||
arr [i] = null;
|
arr [i] = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,26 +4,18 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import buildcraft.core.proxy.CoreProxy;
|
import buildcraft.core.proxy.CoreProxy;
|
||||||
import buildcraft.core.proxy.CoreProxyClient;
|
|
||||||
import cpw.mods.fml.client.FMLClientHandler;
|
|
||||||
import cpw.mods.fml.common.network.Player;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.network.packet.Packet;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraftforge.client.MinecraftForgeClient;
|
|
||||||
import net.minecraftforge.common.DimensionManager;
|
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a first implementation of a RPC connector, using the regular tile
|
* This is a first implementation of a RPC connector, using the regular tile
|
||||||
|
@ -115,6 +107,26 @@ public class RPCHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void rpcBroadcastPlayers (TileEntity tile, String method, int maxDistance, Object ... actuals) {
|
||||||
|
if (!handlers.containsKey(tile.getClass().getName())) {
|
||||||
|
handlers.put (tile.getClass().getName(), new RPCHandler (tile.getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketRPC packet = handlers.get (tile.getClass().getName()).createRCPPacket(tile, method, actuals);
|
||||||
|
|
||||||
|
if (packet != null) {
|
||||||
|
for (Object o : tile.worldObj.playerEntities) {
|
||||||
|
EntityPlayerMP player = (EntityPlayerMP) o;
|
||||||
|
|
||||||
|
if (Math.abs(player.posX - tile.xCoord) <= maxDistance
|
||||||
|
&& Math.abs(player.posY - tile.yCoord) <= maxDistance
|
||||||
|
&& Math.abs(player.posZ - tile.zCoord) <= maxDistance) {
|
||||||
|
CoreProxy.proxy.sendToPlayer(player, packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void receiveRPC (TileEntity tile, RPCMessageInfo info, DataInputStream data) {
|
public static void receiveRPC (TileEntity tile, RPCMessageInfo info, DataInputStream data) {
|
||||||
if (!handlers.containsKey(tile.getClass().getName())) {
|
if (!handlers.containsKey(tile.getClass().getName())) {
|
||||||
handlers.put (tile.getClass().getName(), new RPCHandler (tile.getClass()));
|
handlers.put (tile.getClass().getName(), new RPCHandler (tile.getClass()));
|
||||||
|
@ -210,19 +222,16 @@ public class RPCHandler {
|
||||||
|
|
||||||
m.method.invoke(tile, actuals);
|
m.method.invoke(tile, actuals);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException e) {
|
||||||
// TODO Auto-generated catch block
|
e.printStackTrace();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,10 @@ public class CoreProxy {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SIMULATION */
|
/**
|
||||||
|
* Return true if this world is holding the actual game simulation, that is
|
||||||
|
* for example if this is the server world.
|
||||||
|
*/
|
||||||
public boolean isSimulating(World world) {
|
public boolean isSimulating(World world) {
|
||||||
return !world.isRemote;
|
return !world.isRemote;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue