├── README.md ├── RainCloud-Serialization ├── .classpath ├── .project ├── .settings │ └── org.eclipse.jdt.core.prefs └── src │ └── com │ └── thecherno │ └── raincloud │ └── serialization │ ├── ContainerType.java │ ├── RCArray.java │ ├── RCBase.java │ ├── RCDatabase.java │ ├── RCField.java │ ├── RCObject.java │ ├── RCString.java │ ├── SerializationUtils.java │ └── Type.java └── Sandbox ├── .classpath ├── .project ├── .settings └── org.eclipse.jdt.core.prefs └── src ├── Main.java └── Sandbox.java /README.md: -------------------------------------------------------------------------------- 1 | # JavaSerialization 2 | Source code from my YouTube Serialization series: https://www.youtube.com/playlist?list=PLlrATfBNZ98cCfmH0xPebdVVMSYRQfyKi 3 | -------------------------------------------------------------------------------- /RainCloud-Serialization/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /RainCloud-Serialization/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | RainCloud-Serialization 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /RainCloud-Serialization/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/ContainerType.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | public class ContainerType { 4 | 5 | public static final byte UNKNOWN = 0; 6 | public static final byte FIELD = 1; 7 | public static final byte ARRAY = 2; 8 | public static final byte STRING = 3; 9 | public static final byte OBJECT = 4; 10 | public static final byte DATABASE = 5; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCArray.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public class RCArray extends RCBase { 8 | 9 | public static final byte CONTAINER_TYPE = ContainerType.ARRAY; 10 | public byte type; 11 | public int count; 12 | public byte[] data; 13 | 14 | private short[] shortData; 15 | private char[] charData; 16 | private int[] intData; 17 | private long[] longData; 18 | private float[] floatData; 19 | private double[] doubleData; 20 | private boolean[] booleanData; 21 | 22 | private RCArray() { 23 | size += 1 + 1 + 4; 24 | } 25 | 26 | private void updateSize() { 27 | size += getDataSize(); 28 | } 29 | 30 | public int getBytes(byte[] dest, int pointer) { 31 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 32 | pointer = writeBytes(dest, pointer, nameLength); 33 | pointer = writeBytes(dest, pointer, name); 34 | pointer = writeBytes(dest, pointer, size); 35 | pointer = writeBytes(dest, pointer, type); 36 | pointer = writeBytes(dest, pointer, count); 37 | 38 | switch(type) { 39 | case Type.BYTE: 40 | pointer = writeBytes(dest, pointer, data); 41 | break; 42 | case Type.SHORT: 43 | pointer = writeBytes(dest, pointer, shortData); 44 | break; 45 | case Type.CHAR: 46 | pointer = writeBytes(dest, pointer, charData); 47 | break; 48 | case Type.INTEGER: 49 | pointer = writeBytes(dest, pointer, intData); 50 | break; 51 | case Type.LONG: 52 | pointer = writeBytes(dest, pointer, longData); 53 | break; 54 | case Type.FLOAT: 55 | pointer = writeBytes(dest, pointer, floatData); 56 | break; 57 | case Type.DOUBLE: 58 | pointer = writeBytes(dest, pointer, doubleData); 59 | break; 60 | case Type.BOOLEAN: 61 | pointer = writeBytes(dest, pointer, booleanData); 62 | break; 63 | } 64 | return pointer; 65 | } 66 | 67 | public int getSize() { 68 | return size; 69 | } 70 | 71 | public int getDataSize() { 72 | switch(type) { 73 | case Type.BYTE: return data.length * Type.getSize(Type.BYTE); 74 | case Type.SHORT: return shortData.length * Type.getSize(Type.SHORT); 75 | case Type.CHAR: return charData.length * Type.getSize(Type.CHAR); 76 | case Type.INTEGER: return intData.length * Type.getSize(Type.INTEGER); 77 | case Type.LONG: return longData.length * Type.getSize(Type.LONG); 78 | case Type.FLOAT: return floatData.length * Type.getSize(Type.FLOAT); 79 | case Type.DOUBLE: return doubleData.length * Type.getSize(Type.DOUBLE); 80 | case Type.BOOLEAN: return booleanData.length * Type.getSize(Type.BOOLEAN); 81 | } 82 | return 0; 83 | } 84 | 85 | public static RCArray Byte(String name, byte[] data) { 86 | RCArray array = new RCArray(); 87 | array.setName(name); 88 | array.type = Type.BYTE; 89 | array.count = data.length; 90 | array.data = data; 91 | array.updateSize(); 92 | return array; 93 | } 94 | 95 | public static RCArray Short(String name, short[] data) { 96 | RCArray array = new RCArray(); 97 | array.setName(name); 98 | array.type = Type.SHORT; 99 | array.count = data.length; 100 | array.shortData = data; 101 | array.updateSize(); 102 | return array; 103 | } 104 | 105 | public static RCArray Char(String name, char[] data) { 106 | RCArray array = new RCArray(); 107 | array.setName(name); 108 | array.type = Type.CHAR; 109 | array.count = data.length; 110 | array.charData = data; 111 | array.updateSize(); 112 | return array; 113 | } 114 | 115 | public static RCArray Integer(String name, int[] data) { 116 | RCArray array = new RCArray(); 117 | array.setName(name); 118 | array.type = Type.INTEGER; 119 | array.count = data.length; 120 | array.intData = data; 121 | array.updateSize(); 122 | return array; 123 | } 124 | 125 | public static RCArray Long(String name, long[] data) { 126 | RCArray array = new RCArray(); 127 | array.setName(name); 128 | array.type = Type.LONG; 129 | array.count = data.length; 130 | array.longData = data; 131 | array.updateSize(); 132 | return array; 133 | } 134 | 135 | public static RCArray Float(String name, float[] data) { 136 | RCArray array = new RCArray(); 137 | array.setName(name); 138 | array.type = Type.FLOAT; 139 | array.count = data.length; 140 | array.floatData = data; 141 | array.updateSize(); 142 | return array; 143 | } 144 | 145 | public static RCArray Double(String name, double[] data) { 146 | RCArray array = new RCArray(); 147 | array.setName(name); 148 | array.type = Type.DOUBLE; 149 | array.count = data.length; 150 | array.doubleData = data; 151 | array.updateSize(); 152 | return array; 153 | } 154 | 155 | public static RCArray Boolean(String name, boolean[] data) { 156 | RCArray array = new RCArray(); 157 | array.setName(name); 158 | array.type = Type.BOOLEAN; 159 | array.count = data.length; 160 | array.booleanData = data; 161 | array.updateSize(); 162 | return array; 163 | } 164 | 165 | public static RCArray Deserialize(byte[] data, int pointer) { 166 | byte containerType = data[pointer++]; 167 | assert(containerType == CONTAINER_TYPE); 168 | 169 | RCArray result = new RCArray(); 170 | result.nameLength = readShort(data, pointer); 171 | pointer += 2; 172 | result.name = readString(data, pointer, result.nameLength).getBytes(); 173 | pointer += result.nameLength; 174 | 175 | result.size = readInt(data, pointer); 176 | pointer += 4; 177 | 178 | result.type = data[pointer++]; 179 | 180 | result.count = readInt(data, pointer); 181 | pointer += 4; 182 | 183 | switch(result.type) { 184 | case Type.BYTE: 185 | result.data = new byte[result.count]; 186 | readBytes(data, pointer, result.data); 187 | break; 188 | case Type.SHORT: 189 | result.shortData = new short[result.count]; 190 | readShorts(data, pointer, result.shortData); 191 | break; 192 | case Type.CHAR: 193 | result.charData = new char[result.count]; 194 | readChars(data, pointer, result.charData); 195 | break; 196 | case Type.INTEGER: 197 | result.intData = new int[result.count]; 198 | readInts(data, pointer, result.intData); 199 | break; 200 | case Type.LONG: 201 | result.longData = new long[result.count]; 202 | readLongs(data, pointer, result.longData); 203 | break; 204 | case Type.FLOAT: 205 | result.floatData = new float[result.count]; 206 | readFloats(data, pointer, result.floatData); 207 | break; 208 | case Type.DOUBLE: 209 | result.doubleData = new double[result.count]; 210 | readDoubles(data, pointer, result.doubleData); 211 | break; 212 | case Type.BOOLEAN: 213 | result.booleanData = new boolean[result.count]; 214 | readBooleans(data, pointer, result.booleanData); 215 | break; 216 | } 217 | 218 | pointer += result.count * Type.getSize(result.type); 219 | 220 | return result; 221 | } 222 | 223 | } 224 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCBase.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | public abstract class RCBase { 4 | 5 | protected short nameLength; 6 | protected byte[] name; 7 | 8 | protected int size = 2 + 4; 9 | 10 | public String getName() { 11 | return new String(name, 0, nameLength); 12 | } 13 | 14 | public void setName(String name) { 15 | assert(name.length() < Short.MAX_VALUE); 16 | 17 | if (this.name != null) 18 | size -= this.name.length; 19 | 20 | nameLength = (short)name.length(); 21 | this.name = name.getBytes(); 22 | size += nameLength; 23 | } 24 | 25 | public abstract int getSize(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCDatabase.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | import java.io.BufferedInputStream; 6 | import java.io.BufferedOutputStream; 7 | import java.io.FileInputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class RCDatabase extends RCBase { 14 | 15 | public static final byte[] HEADER = "RCDB".getBytes(); 16 | public static final short VERSION = 0x0100; 17 | public static final byte CONTAINER_TYPE = ContainerType.DATABASE; 18 | private short objectCount; 19 | public List objects = new ArrayList(); 20 | 21 | private RCDatabase() { 22 | } 23 | 24 | public RCDatabase(String name) { 25 | setName(name); 26 | 27 | size += HEADER.length + 2 + 1 + 2; 28 | } 29 | 30 | public void addObject(RCObject object) { 31 | objects.add(object); 32 | size += object.getSize(); 33 | 34 | objectCount = (short)objects.size(); 35 | } 36 | 37 | public int getSize() { 38 | return size; 39 | } 40 | 41 | public int getBytes(byte[] dest, int pointer) { 42 | pointer = writeBytes(dest, pointer, HEADER); 43 | pointer = writeBytes(dest, pointer, VERSION); 44 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 45 | pointer = writeBytes(dest, pointer, nameLength); 46 | pointer = writeBytes(dest, pointer, name); 47 | pointer = writeBytes(dest, pointer, size); 48 | 49 | pointer = writeBytes(dest, pointer, objectCount); 50 | for (RCObject object : objects) 51 | pointer = object.getBytes(dest, pointer); 52 | 53 | return pointer; 54 | } 55 | 56 | public static RCDatabase Deserialize(byte[] data) { 57 | int pointer = 0; 58 | assert(readString(data, pointer, HEADER.length).equals(HEADER)); 59 | pointer += HEADER.length; 60 | 61 | if (readShort(data, pointer) != VERSION) { 62 | System.err.println("Invalid RCDB version!"); 63 | return null; 64 | } 65 | pointer += 2; 66 | 67 | byte containerType = readByte(data, pointer++); 68 | assert(containerType == CONTAINER_TYPE); 69 | 70 | RCDatabase result = new RCDatabase(); 71 | result.nameLength = readShort(data, pointer); 72 | pointer += 2; 73 | result.name = readString(data, pointer, result.nameLength).getBytes(); 74 | pointer += result.nameLength; 75 | 76 | result.size = readInt(data, pointer); 77 | pointer += 4; 78 | 79 | result.objectCount = readShort(data, pointer); 80 | pointer += 2; 81 | 82 | for (int i = 0; i < result.objectCount; i++) { 83 | RCObject object = RCObject.Deserialize(data, pointer); 84 | result.objects.add(object); 85 | pointer += object.getSize(); 86 | } 87 | 88 | return result; 89 | } 90 | 91 | public RCObject findObject(String name) { 92 | for (RCObject object : objects) { 93 | if (object.getName().equals(name)) 94 | return object; 95 | } 96 | return null; 97 | } 98 | 99 | public static RCDatabase DeserializeFromFile(String path) { 100 | byte[] buffer = null; 101 | try { 102 | BufferedInputStream stream = new BufferedInputStream(new FileInputStream(path)); 103 | buffer = new byte[stream.available()]; 104 | stream.read(buffer); 105 | stream.close(); 106 | } catch (IOException e) { 107 | e.printStackTrace(); 108 | } 109 | 110 | return Deserialize(buffer); 111 | } 112 | 113 | public void serializeToFile(String path) { 114 | byte[] data = new byte[getSize()]; 115 | getBytes(data, 0); 116 | try { 117 | BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(path)); 118 | stream.write(data); 119 | stream.close(); 120 | } catch (IOException e) { 121 | e.printStackTrace(); 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCField.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | public class RCField extends RCBase { 6 | 7 | public static final byte CONTAINER_TYPE = ContainerType.FIELD; 8 | public byte type; 9 | public byte[] data; 10 | 11 | private RCField() { 12 | } 13 | 14 | public byte getByte() { 15 | return data[0]; 16 | } 17 | 18 | public short getShort() { 19 | return readShort(data, 0); 20 | } 21 | 22 | public char getChar() { 23 | return readChar(data, 0); 24 | } 25 | 26 | public int getInt() { 27 | return readInt(data, 0); 28 | } 29 | 30 | public long getLong() { 31 | return readLong(data, 0); 32 | } 33 | 34 | public double getDouble() { 35 | return readDouble(data, 0); 36 | } 37 | 38 | public float getFloat() { 39 | return readFloat(data, 0); 40 | } 41 | 42 | public boolean getBoolean() { 43 | return readBoolean(data, 0); 44 | } 45 | 46 | public int getBytes(byte[] dest, int pointer) { 47 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 48 | pointer = writeBytes(dest, pointer, nameLength); 49 | pointer = writeBytes(dest, pointer, name); 50 | pointer = writeBytes(dest, pointer, type); 51 | pointer = writeBytes(dest, pointer, data); 52 | return pointer; 53 | } 54 | 55 | public int getSize() { 56 | assert(data.length == Type.getSize(type)); 57 | return 1 + 2 + name.length + 1 + data.length; 58 | } 59 | 60 | public static RCField Byte(String name, byte value) { 61 | RCField field = new RCField(); 62 | field.setName(name); 63 | field.type = Type.BYTE; 64 | field.data = new byte[Type.getSize(Type.BYTE)]; 65 | writeBytes(field.data, 0, value); 66 | return field; 67 | } 68 | 69 | public static RCField Short(String name, short value) { 70 | RCField field = new RCField(); 71 | field.setName(name); 72 | field.type = Type.SHORT; 73 | field.data = new byte[Type.getSize(Type.SHORT)]; 74 | writeBytes(field.data, 0, value); 75 | return field; 76 | } 77 | 78 | public static RCField Char(String name, char value) { 79 | RCField field = new RCField(); 80 | field.setName(name); 81 | field.type = Type.CHAR; 82 | field.data = new byte[Type.getSize(Type.CHAR)]; 83 | writeBytes(field.data, 0, value); 84 | return field; 85 | } 86 | 87 | public static RCField Integer(String name, int value) { 88 | RCField field = new RCField(); 89 | field.setName(name); 90 | field.type = Type.INTEGER; 91 | field.data = new byte[Type.getSize(Type.INTEGER)]; 92 | writeBytes(field.data, 0, value); 93 | return field; 94 | } 95 | 96 | public static RCField Long(String name, long value) { 97 | RCField field = new RCField(); 98 | field.setName(name); 99 | field.type = Type.LONG; 100 | field.data = new byte[Type.getSize(Type.LONG)]; 101 | writeBytes(field.data, 0, value); 102 | return field; 103 | } 104 | 105 | public static RCField Float(String name, float value) { 106 | RCField field = new RCField(); 107 | field.setName(name); 108 | field.type = Type.FLOAT; 109 | field.data = new byte[Type.getSize(Type.FLOAT)]; 110 | writeBytes(field.data, 0, value); 111 | return field; 112 | } 113 | 114 | public static RCField Double(String name, double value) { 115 | RCField field = new RCField(); 116 | field.setName(name); 117 | field.type = Type.DOUBLE; 118 | field.data = new byte[Type.getSize(Type.DOUBLE)]; 119 | writeBytes(field.data, 0, value); 120 | return field; 121 | } 122 | 123 | public static RCField Boolean(String name, boolean value) { 124 | RCField field = new RCField(); 125 | field.setName(name); 126 | field.type = Type.BOOLEAN; 127 | field.data = new byte[Type.getSize(Type.BOOLEAN)]; 128 | writeBytes(field.data, 0, value); 129 | return field; 130 | } 131 | 132 | public static RCField Deserialize(byte[] data, int pointer) { 133 | byte containerType = data[pointer++]; 134 | assert(containerType == CONTAINER_TYPE); 135 | 136 | RCField result = new RCField(); 137 | result.nameLength = readShort(data, pointer); 138 | pointer += 2; 139 | result.name = readString(data, pointer, result.nameLength).getBytes(); 140 | pointer += result.nameLength; 141 | 142 | result.type = data[pointer++]; 143 | 144 | result.data = new byte[Type.getSize(result.type)]; 145 | readBytes(data, pointer, result.data); 146 | pointer += Type.getSize(result.type); 147 | return result; 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCObject.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class RCObject extends RCBase { 9 | 10 | public static final byte CONTAINER_TYPE = ContainerType.OBJECT; 11 | private short fieldCount; 12 | public List fields = new ArrayList(); 13 | private short stringCount; 14 | public List strings = new ArrayList(); 15 | private short arrayCount; 16 | public List arrays = new ArrayList(); 17 | 18 | private RCObject() { 19 | } 20 | 21 | public RCObject(String name) { 22 | size += 1 + 2 + 2 + 2; 23 | setName(name); 24 | } 25 | 26 | public void addField(RCField field) { 27 | fields.add(field); 28 | size += field.getSize(); 29 | 30 | fieldCount = (short)fields.size(); 31 | } 32 | 33 | public void addString(RCString string) { 34 | strings.add(string); 35 | size += string.getSize(); 36 | 37 | stringCount = (short)strings.size(); 38 | } 39 | 40 | public void addArray(RCArray array) { 41 | arrays.add(array); 42 | size += array.getSize(); 43 | 44 | arrayCount = (short)arrays.size(); 45 | } 46 | 47 | public int getSize() { 48 | return size; 49 | } 50 | 51 | public RCField findField(String name) { 52 | for (RCField field : fields) { 53 | if (field.getName().equals(name)) 54 | return field; 55 | } 56 | return null; 57 | } 58 | 59 | public RCString findString(String name) { 60 | for (RCString string : strings) { 61 | if (string.getName().equals(name)) 62 | return string; 63 | } 64 | return null; 65 | } 66 | 67 | public RCArray findArray(String name) { 68 | for (RCArray array : arrays) { 69 | if (array.getName().equals(name)) 70 | return array; 71 | } 72 | return null; 73 | } 74 | 75 | public int getBytes(byte[] dest, int pointer) { 76 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 77 | pointer = writeBytes(dest, pointer, nameLength); 78 | pointer = writeBytes(dest, pointer, name); 79 | pointer = writeBytes(dest, pointer, size); 80 | 81 | pointer = writeBytes(dest, pointer, fieldCount); 82 | for (RCField field : fields) 83 | pointer = field.getBytes(dest, pointer); 84 | 85 | pointer = writeBytes(dest, pointer, stringCount); 86 | for (RCString string : strings) 87 | pointer = string.getBytes(dest, pointer); 88 | 89 | pointer = writeBytes(dest, pointer, arrayCount); 90 | for (RCArray array : arrays) 91 | pointer = array.getBytes(dest, pointer); 92 | 93 | return pointer; 94 | } 95 | 96 | public static RCObject Deserialize(byte[] data, int pointer) { 97 | byte containerType = data[pointer++]; 98 | assert(containerType == CONTAINER_TYPE); 99 | 100 | RCObject result = new RCObject(); 101 | result.nameLength = readShort(data, pointer); 102 | pointer += 2; 103 | result.name = readString(data, pointer, result.nameLength).getBytes(); 104 | pointer += result.nameLength; 105 | 106 | result.size = readInt(data, pointer); 107 | pointer += 4; 108 | 109 | // Early-out: pointer += result.size - sizeOffset - result.nameLength; 110 | 111 | result.fieldCount = readShort(data, pointer); 112 | pointer += 2; 113 | 114 | for (int i = 0; i < result.fieldCount; i++) { 115 | RCField field = RCField.Deserialize(data, pointer); 116 | result.fields.add(field); 117 | pointer += field.getSize(); 118 | } 119 | 120 | result.stringCount = readShort(data, pointer); 121 | pointer += 2; 122 | 123 | for (int i = 0; i < result.stringCount; i++) { 124 | RCString string = RCString.Deserialize(data, pointer); 125 | result.strings.add(string); 126 | pointer += string.getSize(); 127 | } 128 | 129 | result.arrayCount = readShort(data, pointer); 130 | pointer += 2; 131 | 132 | for (int i = 0; i < result.arrayCount; i++) { 133 | RCArray array = RCArray.Deserialize(data, pointer); 134 | result.arrays.add(array); 135 | pointer += array.getSize(); 136 | } 137 | 138 | return result; 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCString.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | public class RCString extends RCBase { 6 | 7 | public static final byte CONTAINER_TYPE = ContainerType.STRING; 8 | public int count; 9 | private char[] characters; 10 | 11 | private RCString() { 12 | size += 1 + 4; 13 | } 14 | 15 | public String getString() { 16 | return new String(characters); 17 | } 18 | 19 | private void updateSize() { 20 | size += getDataSize(); 21 | } 22 | 23 | public int getBytes(byte[] dest, int pointer) { 24 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 25 | pointer = writeBytes(dest, pointer, nameLength); 26 | pointer = writeBytes(dest, pointer, name); 27 | pointer = writeBytes(dest, pointer, size); 28 | pointer = writeBytes(dest, pointer, count); 29 | pointer = writeBytes(dest, pointer, characters); 30 | return pointer; 31 | } 32 | 33 | public int getSize() { 34 | return size; 35 | } 36 | 37 | public int getDataSize() { 38 | return characters.length * Type.getSize(Type.CHAR); 39 | } 40 | 41 | public static RCString Create(String name, String data) { 42 | RCString string = new RCString(); 43 | string.setName(name); 44 | string.count = data.length(); 45 | string.characters = data.toCharArray(); 46 | string.updateSize(); 47 | return string; 48 | } 49 | 50 | public static RCString Deserialize(byte[] data, int pointer) { 51 | byte containerType = data[pointer++]; 52 | assert(containerType == CONTAINER_TYPE); 53 | 54 | RCString result = new RCString(); 55 | result.nameLength = readShort(data, pointer); 56 | pointer += 2; 57 | result.name = readString(data, pointer, result.nameLength).getBytes(); 58 | pointer += result.nameLength; 59 | 60 | result.size = readInt(data, pointer); 61 | pointer += 4; 62 | 63 | result.count = readInt(data, pointer); 64 | pointer += 4; 65 | 66 | result.characters = new char[result.count]; 67 | readChars(data, pointer, result.characters); 68 | 69 | pointer += result.count * Type.getSize(Type.CHAR); 70 | return result; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/SerializationUtils.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | public class SerializationUtils { 6 | 7 | public static int writeBytes(byte[] dest, int pointer, byte[] src) { 8 | assert(dest.length > pointer + src.length); 9 | for (int i = 0; i < src.length; i++) 10 | dest[pointer++] = src[i]; 11 | return pointer; 12 | } 13 | 14 | public static int writeBytes(byte[] dest, int pointer, char[] src) { 15 | assert(dest.length > pointer + src.length); 16 | for (int i = 0; i < src.length; i++) 17 | pointer = writeBytes(dest, pointer, src[i]); 18 | return pointer; 19 | } 20 | 21 | public static int writeBytes(byte[] dest, int pointer, short[] src) { 22 | assert(dest.length > pointer + src.length); 23 | for (int i = 0; i < src.length; i++) 24 | pointer = writeBytes(dest, pointer, src[i]); 25 | return pointer; 26 | } 27 | 28 | public static int writeBytes(byte[] dest, int pointer, int[] src) { 29 | assert(dest.length > pointer + src.length); 30 | for (int i = 0; i < src.length; i++) 31 | pointer = writeBytes(dest, pointer, src[i]); 32 | return pointer; 33 | } 34 | 35 | public static int writeBytes(byte[] dest, int pointer, long[] src) { 36 | assert(dest.length > pointer + src.length); 37 | for (int i = 0; i < src.length; i++) 38 | pointer = writeBytes(dest, pointer, src[i]); 39 | return pointer; 40 | } 41 | 42 | public static int writeBytes(byte[] dest, int pointer, float[] src) { 43 | assert(dest.length > pointer + src.length); 44 | for (int i = 0; i < src.length; i++) 45 | pointer = writeBytes(dest, pointer, src[i]); 46 | return pointer; 47 | } 48 | 49 | public static int writeBytes(byte[] dest, int pointer, double[] src) { 50 | assert(dest.length > pointer + src.length); 51 | for (int i = 0; i < src.length; i++) 52 | pointer = writeBytes(dest, pointer, src[i]); 53 | return pointer; 54 | } 55 | 56 | public static int writeBytes(byte[] dest, int pointer, boolean[] src) { 57 | assert(dest.length > pointer + src.length); 58 | for (int i = 0; i < src.length; i++) 59 | pointer = writeBytes(dest, pointer, src[i]); 60 | return pointer; 61 | } 62 | 63 | public static int writeBytes(byte[] dest, int pointer, byte value) { 64 | assert(dest.length > pointer + Type.getSize(Type.BYTE)); 65 | dest[pointer++] = value; 66 | return pointer; 67 | } 68 | 69 | public static int writeBytes(byte[] dest, int pointer, short value) { 70 | assert(dest.length > pointer + Type.getSize(Type.SHORT)); 71 | dest[pointer++] = (byte)((value >> 8) & 0xff); 72 | dest[pointer++] = (byte)((value >> 0) & 0xff); 73 | return pointer; 74 | } 75 | 76 | public static int writeBytes(byte[] dest, int pointer, char value) { 77 | assert(dest.length > pointer + Type.getSize(Type.CHAR)); 78 | dest[pointer++] = (byte)((value >> 8) & 0xff); 79 | dest[pointer++] = (byte)((value >> 0) & 0xff); 80 | return pointer; 81 | } 82 | 83 | public static int writeBytes(byte[] dest, int pointer, int value) { 84 | assert(dest.length > pointer + Type.getSize(Type.INTEGER)); 85 | dest[pointer++] = (byte)((value >> 24) & 0xff); 86 | dest[pointer++] = (byte)((value >> 16) & 0xff); 87 | dest[pointer++] = (byte)((value >> 8) & 0xff); 88 | dest[pointer++] = (byte)((value >> 0) & 0xff); 89 | return pointer; 90 | } 91 | 92 | public static int writeBytes(byte[] dest, int pointer, long value) { 93 | assert(dest.length > pointer + Type.getSize(Type.LONG)); 94 | dest[pointer++] = (byte)((value >> 56) & 0xff); 95 | dest[pointer++] = (byte)((value >> 48) & 0xff); 96 | dest[pointer++] = (byte)((value >> 40) & 0xff); 97 | dest[pointer++] = (byte)((value >> 32) & 0xff); 98 | dest[pointer++] = (byte)((value >> 24) & 0xff); 99 | dest[pointer++] = (byte)((value >> 16) & 0xff); 100 | dest[pointer++] = (byte)((value >> 8) & 0xff); 101 | dest[pointer++] = (byte)((value >> 0) & 0xff); 102 | return pointer; 103 | } 104 | 105 | public static int writeBytes(byte[] dest, int pointer, float value) { 106 | assert(dest.length > pointer + Type.getSize(Type.FLOAT)); 107 | int data = Float.floatToIntBits(value); 108 | return writeBytes(dest, pointer, data); 109 | } 110 | 111 | public static int writeBytes(byte[] dest, int pointer, double value) { 112 | assert(dest.length > pointer + Type.getSize(Type.DOUBLE)); 113 | long data = Double.doubleToLongBits(value); 114 | return writeBytes(dest, pointer, data); 115 | } 116 | 117 | public static int writeBytes(byte[] dest, int pointer, boolean value) { 118 | assert(dest.length > pointer + Type.getSize(Type.BOOLEAN)); 119 | dest[pointer++] = (byte)(value ? 1 : 0); 120 | return pointer; 121 | } 122 | 123 | public static int writeBytes(byte[] dest, int pointer, String string) { 124 | pointer = writeBytes(dest, pointer, (short) string.length()); 125 | return writeBytes(dest, pointer, string.getBytes()); 126 | } 127 | 128 | public static byte readByte(byte[] src, int pointer) { 129 | return src[pointer]; 130 | } 131 | 132 | public static void readBytes(byte[] src, int pointer, byte[] dest) { 133 | for (int i = 0; i < dest.length; i++) 134 | dest[i] = src[pointer + i]; 135 | } 136 | 137 | public static void readShorts(byte[] src, int pointer, short[] dest) { 138 | for (int i = 0; i < dest.length; i++) { 139 | dest[i] = readShort(src, pointer); 140 | pointer += Type.getSize(Type.SHORT); 141 | } 142 | } 143 | 144 | public static void readChars(byte[] src, int pointer, char[] dest) { 145 | for (int i = 0; i < dest.length; i++) { 146 | dest[i] = readChar(src, pointer); 147 | pointer += Type.getSize(Type.CHAR); 148 | } 149 | } 150 | 151 | public static void readInts(byte[] src, int pointer, int[] dest) { 152 | for (int i = 0; i < dest.length; i++) { 153 | dest[i] = readInt(src, pointer); 154 | pointer += Type.getSize(Type.INTEGER); 155 | } 156 | } 157 | 158 | public static void readLongs(byte[] src, int pointer, long[] dest) { 159 | for (int i = 0; i < dest.length; i++) { 160 | dest[i] = readLong(src, pointer); 161 | pointer += Type.getSize(Type.LONG); 162 | } 163 | } 164 | 165 | public static void readFloats(byte[] src, int pointer, float[] dest) { 166 | for (int i = 0; i < dest.length; i++) { 167 | dest[i] = readFloat(src, pointer); 168 | pointer += Type.getSize(Type.FLOAT); 169 | } 170 | } 171 | 172 | public static void readDoubles(byte[] src, int pointer, double[] dest) { 173 | for (int i = 0; i < dest.length; i++) { 174 | dest[i] = readDouble(src, pointer); 175 | pointer += Type.getSize(Type.DOUBLE); 176 | } 177 | } 178 | 179 | public static void readBooleans(byte[] src, int pointer, boolean[] dest) { 180 | for (int i = 0; i < dest.length; i++) { 181 | dest[i] = readBoolean(src, pointer); 182 | pointer += Type.getSize(Type.BOOLEAN); 183 | } 184 | } 185 | public static short readShort(byte[] src, int pointer) { 186 | return ByteBuffer.wrap(src, pointer, 2).getShort(); 187 | } 188 | 189 | public static char readChar(byte[] src, int pointer) { 190 | return ByteBuffer.wrap(src, pointer, 2).getChar(); 191 | } 192 | 193 | public static int readInt(byte[] src, int pointer) { 194 | return ByteBuffer.wrap(src, pointer, 4).getInt(); 195 | } 196 | 197 | public static long readLong(byte[] src, int pointer) { 198 | return ByteBuffer.wrap(src, pointer, 8).getLong(); 199 | } 200 | 201 | public static float readFloat(byte[] src, int pointer) { 202 | return Float.intBitsToFloat(readInt(src, pointer)); 203 | } 204 | 205 | public static double readDouble(byte[] src, int pointer) { 206 | return Double.longBitsToDouble(readLong(src, pointer)); 207 | } 208 | 209 | public static boolean readBoolean(byte[] src, int pointer) { 210 | assert(src[pointer] == 0 || src[pointer] == 1); 211 | return src[pointer] != 0; 212 | } 213 | 214 | public static String readString(byte[] src, int pointer, int length) { 215 | return new String(src, pointer, length); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/Type.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | public class Type { 4 | 5 | public static final byte UNKNOWN = 0; 6 | public static final byte BYTE = 1; 7 | public static final byte SHORT = 2; 8 | public static final byte CHAR = 3; 9 | public static final byte INTEGER = 4; 10 | public static final byte LONG = 5; 11 | public static final byte FLOAT = 6; 12 | public static final byte DOUBLE = 7; 13 | public static final byte BOOLEAN = 8; 14 | 15 | public static int getSize(byte type) { 16 | switch (type) { 17 | case BYTE: return 1; 18 | case SHORT: return 2; 19 | case CHAR: return 2; 20 | case INTEGER: return 4; 21 | case LONG: return 8; 22 | case FLOAT: return 4; 23 | case DOUBLE: return 8; 24 | case BOOLEAN: return 1; 25 | } 26 | assert(false); 27 | return 0; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Sandbox/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sandbox/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Sandbox 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /Sandbox/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /Sandbox/src/Main.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedOutputStream; 2 | import java.io.FileOutputStream; 3 | import java.io.IOException; 4 | import java.util.Random; 5 | 6 | import com.thecherno.raincloud.serialization.RCArray; 7 | import com.thecherno.raincloud.serialization.RCBase; 8 | import com.thecherno.raincloud.serialization.RCDatabase; 9 | import com.thecherno.raincloud.serialization.RCField; 10 | import com.thecherno.raincloud.serialization.RCObject; 11 | import com.thecherno.raincloud.serialization.RCString; 12 | 13 | public class Main { 14 | 15 | static Random random = new Random(); 16 | 17 | static void printBytes(byte[] data) { 18 | for (int i = 0; i < data.length; i++) { 19 | System.out.printf("0x%x ", data[i]); 20 | } 21 | } 22 | 23 | public static void serializationTest() { 24 | int[] data = new int[50000]; 25 | for (int i = 0; i < data.length; i++) { 26 | data[i] = random.nextInt(); 27 | } 28 | 29 | RCDatabase database = new RCDatabase("Database"); 30 | RCArray array = RCArray.Integer("RandomNumbers", data); 31 | RCField field = RCField.Integer("Integer", 8); 32 | RCField positionx = RCField.Short("xpos", (short)2); 33 | RCField positiony = RCField.Short("ypos", (short)43); 34 | 35 | RCObject object = new RCObject("Entity"); 36 | object.addArray(array); 37 | object.addArray(RCArray.Char("String", "Hello World!".toCharArray())); 38 | object.addField(field); 39 | object.addField(positionx); 40 | object.addField(positiony); 41 | object.addString(RCString.Create("Example String", "Testing our RCString class!")); 42 | 43 | database.addObject(object); 44 | database.addObject(new RCObject("Cherno")); 45 | database.addObject(new RCObject("Cherno1")); 46 | RCObject c = new RCObject("Cherno2"); 47 | c.addField(RCField.Boolean("a", false)); 48 | database.addObject(c); 49 | database.addObject(new RCObject("Cherno3")); 50 | 51 | database.serializeToFile("test.rcd"); 52 | } 53 | 54 | public static void deserializationTest() { 55 | RCDatabase database = RCDatabase.DeserializeFromFile("test.rcd"); 56 | System.out.println("Database: " + database.getName()); 57 | for (RCObject object : database.objects) { 58 | System.out.println("\t" + object.getName()); 59 | for (RCField field : object.fields) 60 | System.out.println("\t\t" + field.getName()); 61 | System.out.println(); 62 | for (RCString string : object.strings) 63 | System.out.println("\t\t" + string.getName() + " = " + string.getString()); 64 | System.out.println(); 65 | for (RCArray array : object.arrays) 66 | System.out.println("\t\t" + array.getName()); 67 | System.out.println(); 68 | } 69 | System.out.println(); 70 | } 71 | 72 | public static void main(String[] args) { 73 | // serializationTest(); 74 | // deserializationTest(); 75 | 76 | Sandbox sandbox = new Sandbox(); 77 | sandbox.play(); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /Sandbox/src/Sandbox.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | import com.thecherno.raincloud.serialization.RCDatabase; 5 | import com.thecherno.raincloud.serialization.RCField; 6 | import com.thecherno.raincloud.serialization.RCObject; 7 | import com.thecherno.raincloud.serialization.RCString; 8 | 9 | public class Sandbox { 10 | 11 | static class Level { 12 | 13 | private String name; 14 | private String path; 15 | private int width, height; 16 | private List entities = new ArrayList(); 17 | 18 | private Level() { 19 | } 20 | 21 | public Level(String path) { 22 | this.name = "Level One"; 23 | this.path = path; 24 | width = 64; 25 | height = 128; 26 | } 27 | 28 | public void add(Entity e) { 29 | e.init(this); 30 | entities.add(e); 31 | } 32 | 33 | public void update() { 34 | } 35 | 36 | public void render() { 37 | } 38 | 39 | public void save(String path) { 40 | RCDatabase database = new RCDatabase(name); 41 | RCObject object = new RCObject("LevelData"); 42 | object.addString(RCString.Create("name", name)); 43 | object.addString(RCString.Create("path", this.path)); 44 | object.addField(RCField.Integer("width", width)); 45 | object.addField(RCField.Integer("height", height)); 46 | object.addField(RCField.Integer("entityCount", entities.size())); 47 | database.addObject(object); 48 | for (int i = 0; i < entities.size(); i++) { 49 | Entity e = entities.get(i); 50 | 51 | RCObject entity = new RCObject("E" + i); 52 | byte type = 0; 53 | if (e instanceof Player) 54 | type = 1; 55 | entity.addField(RCField.Byte("type", type)); 56 | entity.addField(RCField.Integer("arrayIndex", i)); 57 | e.serialize(entity); 58 | database.addObject(entity); 59 | } 60 | 61 | database.serializeToFile(path); 62 | } 63 | 64 | public static Level load(String path) { 65 | RCDatabase database = RCDatabase.DeserializeFromFile(path); 66 | RCObject levelData = database.findObject("LevelData"); 67 | 68 | Level result = new Level(); 69 | result.name = levelData.findString("name").getString(); 70 | result.path = levelData.findString("path").getString(); 71 | result.width = levelData.findField("width").getInt(); 72 | result.height = levelData.findField("height").getInt(); 73 | int entityCount = levelData.findField("entityCount").getInt(); 74 | 75 | for (int i = 0; i < entityCount; i++) { 76 | RCObject entity = database.findObject("E" + i); 77 | Entity e; 78 | if (entity.findField("type").getByte() == 1) 79 | e = Player.deserialize(entity); 80 | else 81 | e = Entity.deserialize(entity); 82 | result.add(e); 83 | } 84 | return result; 85 | } 86 | 87 | } 88 | 89 | static class Entity { 90 | 91 | protected int x, y; 92 | protected boolean removed = false; 93 | protected Level level; 94 | 95 | public Entity() { 96 | x = 0; 97 | y = 0; 98 | } 99 | 100 | public void init(Level level) { 101 | this.level = level; 102 | } 103 | 104 | public void serialize(RCObject object) { 105 | object.addField(RCField.Integer("x", x)); 106 | object.addField(RCField.Integer("y", y)); 107 | object.addField(RCField.Boolean("removed", removed)); 108 | } 109 | 110 | public static Entity deserialize(RCObject object) { 111 | Entity result = new Entity(); 112 | result.x = object.findField("x").getInt(); 113 | result.y = object.findField("y").getInt(); 114 | result.removed = object.findField("removed").getBoolean(); 115 | return result; 116 | } 117 | 118 | } 119 | 120 | static class Player extends Entity { 121 | 122 | private String name; 123 | private String avatarPath; 124 | 125 | private Player() { 126 | } 127 | 128 | public Player(String name, int x, int y) { 129 | this.x = x; 130 | this.y = y; 131 | 132 | this.name = name; 133 | avatarPath = "res/avatar.png"; 134 | } 135 | 136 | public void serialize(RCObject object) { 137 | super.serialize(object); 138 | object.addString(RCString.Create("name", name)); 139 | object.addString(RCString.Create("avatarPath", avatarPath)); 140 | } 141 | 142 | public static Player deserialize(RCObject object) { 143 | Entity e = Entity.deserialize(object); 144 | 145 | Player result = new Player(); 146 | result.x = e.x; 147 | result.y = e.y; 148 | result.removed = e.removed; 149 | 150 | result.name = object.findString("name").getString(); 151 | result.avatarPath = object.findString("avatarPath").getString(); 152 | 153 | return result; 154 | } 155 | 156 | } 157 | 158 | public void play() { 159 | { 160 | Entity mob = new Entity(); 161 | Player player = new Player("Cherno", 40, 28); 162 | 163 | Level level = new Level("res/level.lvl"); 164 | level.add(mob); 165 | level.add(player); 166 | 167 | level.save("level.rcd"); 168 | } 169 | { 170 | Level level = Level.load("level.rcd"); 171 | System.out.println(); 172 | } 173 | } 174 | 175 | } 176 | --------------------------------------------------------------------------------