[PlutoUSS2/PlutoLib] Added PlutoUSS2
This commit is contained in:
parent
2ec489ee65
commit
9711c7d05b
|
@ -30,6 +30,7 @@ version numbers.*
|
||||||
* **PlutoShader** - Stable
|
* **PlutoShader** - Stable
|
||||||
* **PlutoSpriteSheet** - Stable, some features are unfinished
|
* **PlutoSpriteSheet** - Stable, some features are unfinished
|
||||||
* **PlutoStatic** - Stable, collision API nowhere near completion
|
* **PlutoStatic** - Stable, collision API nowhere near completion
|
||||||
|
* **PlutoUSS2** - Stable
|
||||||
|
|
||||||
### Unstable submodules
|
### Unstable submodules
|
||||||
* **PlutoAudio** - Somewhat usable, unfinished
|
* **PlutoAudio** - Somewhat usable, unfinished
|
||||||
|
@ -64,7 +65,7 @@ See `NEXT_RELEASE_DRAFT.md` for details.
|
||||||
[ *Items not required immediately, planned to be implemented eventually.* ]
|
[ *Items not required immediately, planned to be implemented eventually.* ]
|
||||||
* Allow multiple running instances of Pluto
|
* Allow multiple running instances of Pluto
|
||||||
* Alternatively, if this deems too difficult to implement,
|
* Alternatively, if this deems too difficult to implement,
|
||||||
prohibit the creation of more than instance per VM to avoid issues
|
prohibit the creation of more than one instance per JVM to avoid issues
|
||||||
* A networking API
|
* A networking API
|
||||||
* Expand upon the Color API
|
* Expand upon the Color API
|
||||||
* Color mixing and blending
|
* Color mixing and blending
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
## 20.2.0.0-alpha.3
|
## 20.2.0.0-alpha.3
|
||||||
|
* `[PlutoUSS2]` **Added USS2 as a new module**
|
||||||
|
* `[PlutoLib]` `PlutoLib` now depends on `PlutoUSS2`
|
||||||
* `[PlutoLib]` *Removed* `Severity`, use `SmartSeverity` instead
|
* `[PlutoLib]` *Removed* `Severity`, use `SmartSeverity` instead
|
||||||
* `[PlutoLib]` *Removed* `TextIn`, `TextOut`, `ResourceImage` and `ResourceInputStream`
|
* `[PlutoLib]` *Removed* `TextIn`, `TextOut`, `ResourceImage` and `ResourceInputStream`
|
||||||
* `[PlutoLib]` *Removed* `StaticPlutoEventManager` as the implementation was too obscure
|
* `[PlutoLib]` *Removed* `StaticPlutoEventManager` as the implementation was too obscure
|
||||||
|
@ -18,7 +20,7 @@
|
||||||
* `[PlutoLib]` Created the Version API
|
* `[PlutoLib]` Created the Version API
|
||||||
* Added the `IVersion` interface
|
* Added the `IVersion` interface
|
||||||
* Added support for version objects
|
* Added support for version objects
|
||||||
* As a result, all fields except the version string are no longer compile-time constants
|
* As a result, all fields in `Pluto` except the version string are no longer compile-time constants
|
||||||
* `[PlutoCore]` Made `PlutoApplication`'s constructor private
|
* `[PlutoCore]` Made `PlutoApplication`'s constructor private
|
||||||
* `[PlutoLib]` `MiniTimeParseException` no longer contains a hardcoded String message
|
* `[PlutoLib]` `MiniTimeParseException` no longer contains a hardcoded String message
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ task generateConfigs(type: Copy) {
|
||||||
compileJava.dependsOn generateConfigs
|
compileJava.dependsOn generateConfigs
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
api project(":plutouss2")
|
||||||
|
|
||||||
api platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
|
api platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
|
||||||
|
|
||||||
api "com.google.code.findbugs:jsr305:3.0.2"
|
api "com.google.code.findbugs:jsr305:3.0.2"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
|
description = "UniversalSerializationSystem 2 (formerly UserStorageSystem) is a simple library for " +
|
||||||
|
"in-memory serialization of basic data types to ByteBuffers with versioned schema support."
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package cz.tefek.pluto.uss2.properties;
|
||||||
|
|
||||||
|
public enum EnumUSS2PropertyType
|
||||||
|
{
|
||||||
|
BYTE,
|
||||||
|
INT,
|
||||||
|
LONG,
|
||||||
|
STRING,
|
||||||
|
DOUBLE
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package cz.tefek.pluto.uss2.properties;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public final class USS2PropertyObject
|
||||||
|
{
|
||||||
|
final USS2PropertySchema schema;
|
||||||
|
|
||||||
|
final int currentVersion;
|
||||||
|
final int latestVersion;
|
||||||
|
boolean dirty;
|
||||||
|
|
||||||
|
final ByteBuffer data;
|
||||||
|
|
||||||
|
private USS2PropertyObject(ByteBuffer buf, USS2PropertySchema schema)
|
||||||
|
{
|
||||||
|
this.schema = schema;
|
||||||
|
|
||||||
|
if (buf.limit() != schema.getCapacity())
|
||||||
|
throw new IllegalArgumentException("The input ByteBuffer's limit and the USS2PropertySchema size must be the same value!");
|
||||||
|
|
||||||
|
this.currentVersion = 0xff & buf.get(0);
|
||||||
|
this.latestVersion = schema.getVersion();
|
||||||
|
|
||||||
|
if (this.currentVersion > this.latestVersion)
|
||||||
|
throw new RuntimeException(String.format("The file's version (%d) is newer than what USS2 can read (%d)!", this.currentVersion, this.latestVersion));
|
||||||
|
|
||||||
|
this.data = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static USS2PropertyObject upgrade(USS2PropertyObject po)
|
||||||
|
{
|
||||||
|
var poNew = create(po.schema);
|
||||||
|
var props = po.schema.getProperties();
|
||||||
|
props.forEach(property -> {
|
||||||
|
if (property instanceof USS2PropertySchema.USS2Int)
|
||||||
|
{
|
||||||
|
var ussInt = (USS2PropertySchema.USS2Int) property;
|
||||||
|
ussInt.write(poNew, ussInt.read(po));
|
||||||
|
}
|
||||||
|
else if (property instanceof USS2PropertySchema.USS2Long)
|
||||||
|
{
|
||||||
|
var ussLong = (USS2PropertySchema.USS2Long) property;
|
||||||
|
ussLong.write(poNew, ussLong.read(po));
|
||||||
|
}
|
||||||
|
else if (property instanceof USS2PropertySchema.USS2Double)
|
||||||
|
{
|
||||||
|
var ussDouble = (USS2PropertySchema.USS2Double) property;
|
||||||
|
ussDouble.write(poNew, ussDouble.read(po));
|
||||||
|
}
|
||||||
|
else if (property instanceof USS2PropertySchema.USS2Byte)
|
||||||
|
{
|
||||||
|
var ussByte = (USS2PropertySchema.USS2Byte) property;
|
||||||
|
ussByte.write(poNew, ussByte.read(po));
|
||||||
|
}
|
||||||
|
else if (property instanceof USS2PropertySchema.USS2String)
|
||||||
|
{
|
||||||
|
var ussString = (USS2PropertySchema.USS2String) property;
|
||||||
|
ussString.write(poNew, ussString.read(po));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return poNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static USS2PropertyObject create(USS2PropertySchema schema)
|
||||||
|
{
|
||||||
|
var buf = ByteBuffer.wrap(new byte[schema.getCapacity()]);
|
||||||
|
buf.put(0, (byte) schema.getVersion());
|
||||||
|
|
||||||
|
var po = new USS2PropertyObject(buf, schema);
|
||||||
|
po.dirty = true;
|
||||||
|
|
||||||
|
return po;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static USS2PropertyObject from(ByteBuffer buf, USS2PropertySchema schema)
|
||||||
|
{
|
||||||
|
var po = new USS2PropertyObject(buf, schema);
|
||||||
|
|
||||||
|
if (po.latestVersion != po.currentVersion)
|
||||||
|
return upgrade(po);
|
||||||
|
|
||||||
|
return po;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getData()
|
||||||
|
{
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getDataByteArray()
|
||||||
|
{
|
||||||
|
if (!this.data.hasArray())
|
||||||
|
throw new RuntimeException("Data does not have a backing array!");
|
||||||
|
|
||||||
|
return this.data.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDirty()
|
||||||
|
{
|
||||||
|
return this.dirty;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,273 @@
|
||||||
|
package cz.tefek.pluto.uss2.properties;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class USS2PropertySchema
|
||||||
|
{
|
||||||
|
public static final int DOES_NOT_EXIST_IN_VERSION = -1;
|
||||||
|
public static final int MAX_VERSION = 0xff;
|
||||||
|
|
||||||
|
private final List<USS2Property> properties;
|
||||||
|
|
||||||
|
private final int capacity;
|
||||||
|
|
||||||
|
private int version;
|
||||||
|
private final int[] offsets;
|
||||||
|
|
||||||
|
protected USS2PropertySchema(int capacity)
|
||||||
|
{
|
||||||
|
if (capacity < 16)
|
||||||
|
throw new IllegalArgumentException("Please use a starting capacity of at least 16 bytes.");
|
||||||
|
|
||||||
|
this.properties = new ArrayList<>();
|
||||||
|
this.offsets = new int[MAX_VERSION + 1];
|
||||||
|
|
||||||
|
// Version byte
|
||||||
|
Arrays.fill(this.offsets, Byte.BYTES);
|
||||||
|
|
||||||
|
this.capacity = capacity;
|
||||||
|
this.version = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getInfo()
|
||||||
|
{
|
||||||
|
float used = this.offsets[MAX_VERSION] / (float) this.capacity;
|
||||||
|
final int bars = 30;
|
||||||
|
int usedBars = Math.round(used * bars);
|
||||||
|
|
||||||
|
return String.format("[%s%s] %.2f%% of schema used (%d/%d bytes).", "|".repeat(usedBars), " ".repeat(bars - usedBars), used * 100, this.offsets[MAX_VERSION], this.capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void declareProperty(USS2Property property)
|
||||||
|
{
|
||||||
|
Arrays.fill(property.offsets, 0, property.version, DOES_NOT_EXIST_IN_VERSION);
|
||||||
|
System.arraycopy(this.offsets, property.version, property.offsets, property.version, property.offsets.length - property.version);
|
||||||
|
|
||||||
|
// No need to check all versions, because the highest version is the largest by default (properties cannot be removed)
|
||||||
|
if (this.offsets[MAX_VERSION] + property.objectSize > this.capacity)
|
||||||
|
throw new IllegalStateException(
|
||||||
|
String.format("Error: Declaring another property (of size %d) " +
|
||||||
|
"would put the schema's total size to %d, which is over the capacity of %d.",
|
||||||
|
property.objectSize,
|
||||||
|
this.offsets[MAX_VERSION] + property.objectSize,
|
||||||
|
this.capacity));
|
||||||
|
|
||||||
|
this.properties.add(property);
|
||||||
|
|
||||||
|
if (property.version > this.version)
|
||||||
|
this.version = property.version;
|
||||||
|
|
||||||
|
for (int i = property.version; i <= MAX_VERSION; i++)
|
||||||
|
this.offsets[i] += property.objectSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final List<USS2Property> getProperties()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableList(this.properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getVersion()
|
||||||
|
{
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getCapacity()
|
||||||
|
{
|
||||||
|
return this.capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final USS2Int declareInt(byte version)
|
||||||
|
{
|
||||||
|
var ussInt = new USS2Int(0xff & version);
|
||||||
|
this.declareProperty(ussInt);
|
||||||
|
return ussInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final USS2Long declareLong(byte version)
|
||||||
|
{
|
||||||
|
var ussLong = new USS2Long(0xff & version);
|
||||||
|
this.declareProperty(ussLong);
|
||||||
|
return ussLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final USS2Double declareDouble(byte version)
|
||||||
|
{
|
||||||
|
var ussDouble = new USS2Double(0xff & version);
|
||||||
|
this.declareProperty(ussDouble);
|
||||||
|
return ussDouble;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final USS2Byte declareByte(byte version)
|
||||||
|
{
|
||||||
|
var ussByte = new USS2Byte(0xff & version);
|
||||||
|
this.declareProperty(ussByte);
|
||||||
|
return ussByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final USS2String declareString(byte version, byte length)
|
||||||
|
{
|
||||||
|
var ussByte = new USS2String(0xff & version, 0xff & length);
|
||||||
|
this.declareProperty(ussByte);
|
||||||
|
return ussByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class USS2Property
|
||||||
|
{
|
||||||
|
private final int version;
|
||||||
|
private final int objectSize;
|
||||||
|
protected final int[] offsets;
|
||||||
|
|
||||||
|
protected USS2Property(int version, int objectSize)
|
||||||
|
{
|
||||||
|
this.version = version;
|
||||||
|
this.objectSize = objectSize;
|
||||||
|
this.offsets = new int[MAX_VERSION];
|
||||||
|
}
|
||||||
|
|
||||||
|
final int getObjectSize()
|
||||||
|
{
|
||||||
|
return this.objectSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getVersion()
|
||||||
|
{
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class USS2Int extends USS2Property
|
||||||
|
{
|
||||||
|
private USS2Int(int version)
|
||||||
|
{
|
||||||
|
super(version, Integer.BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void write(USS2PropertyObject po, int value)
|
||||||
|
{
|
||||||
|
po.dirty = true;
|
||||||
|
po.data.putInt(this.offsets[po.currentVersion], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int read(USS2PropertyObject po)
|
||||||
|
{
|
||||||
|
if (this.offsets[po.currentVersion] == DOES_NOT_EXIST_IN_VERSION)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return po.data.getInt(this.offsets[po.currentVersion]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class USS2Long extends USS2Property
|
||||||
|
{
|
||||||
|
private USS2Long(int version)
|
||||||
|
{
|
||||||
|
super(version, Long.BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void write(USS2PropertyObject po, long value)
|
||||||
|
{
|
||||||
|
po.dirty = true;
|
||||||
|
po.data.putLong(this.offsets[po.currentVersion], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final long read(USS2PropertyObject po)
|
||||||
|
{
|
||||||
|
if (this.offsets[po.currentVersion] == DOES_NOT_EXIST_IN_VERSION)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return po.data.getLong(this.offsets[po.currentVersion]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class USS2Double extends USS2Property
|
||||||
|
{
|
||||||
|
private USS2Double(int version)
|
||||||
|
{
|
||||||
|
super(version, Double.BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void write(USS2PropertyObject po, double value)
|
||||||
|
{
|
||||||
|
po.dirty = true;
|
||||||
|
po.data.putDouble(this.offsets[po.currentVersion], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final double read(USS2PropertyObject po)
|
||||||
|
{
|
||||||
|
if (this.offsets[po.currentVersion] == DOES_NOT_EXIST_IN_VERSION)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return po.data.getDouble(this.offsets[po.currentVersion]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class USS2Byte extends USS2Property
|
||||||
|
{
|
||||||
|
public USS2Byte(int version)
|
||||||
|
{
|
||||||
|
super(version, Byte.BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void write(USS2PropertyObject po, byte value)
|
||||||
|
{
|
||||||
|
po.dirty = true;
|
||||||
|
po.data.put(this.offsets[po.currentVersion], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte read(USS2PropertyObject po)
|
||||||
|
{
|
||||||
|
if (this.offsets[po.currentVersion] == DOES_NOT_EXIST_IN_VERSION)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return po.data.get(this.offsets[po.currentVersion]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class USS2String extends USS2Property
|
||||||
|
{
|
||||||
|
private USS2String(int version, int length)
|
||||||
|
{
|
||||||
|
super(version, Byte.BYTES + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void write(USS2PropertyObject po, String value)
|
||||||
|
{
|
||||||
|
po.dirty = true;
|
||||||
|
var offset = this.offsets[po.currentVersion];
|
||||||
|
var data = value.getBytes(StandardCharsets.UTF_8);
|
||||||
|
po.data.position(offset);
|
||||||
|
po.data.put((byte) data.length);
|
||||||
|
po.data.put(data);
|
||||||
|
po.data.rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String read(USS2PropertyObject po)
|
||||||
|
{
|
||||||
|
if (this.offsets[po.currentVersion] == DOES_NOT_EXIST_IN_VERSION)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset = this.offsets[po.currentVersion];
|
||||||
|
po.data.position(offset);
|
||||||
|
var length = po.data.get();
|
||||||
|
var bytes = new byte[0xff & length];
|
||||||
|
po.data.get(bytes);
|
||||||
|
po.data.rewind();
|
||||||
|
|
||||||
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
include 'plutolib',
|
include 'plutouss2',
|
||||||
|
'plutolib',
|
||||||
'plutostatic',
|
'plutostatic',
|
||||||
'plutotexturing',
|
'plutotexturing',
|
||||||
'plutomesher',
|
'plutomesher',
|
||||||
|
|
Loading…
Reference in New Issue