Refactored Namespaced stuff

- Namespaced now takes full ID in constructor
  - Changed the rest of source accordingly
- Moved everything related to Namespaced into .util.namespaced package
- Errors are now reported with IllegalIdException instead of IAE
- Error checking is optimized
- NamespacedUtil exposes more of its requirements
- Added StringUtil.splitAt
- Added ArrayUtil.isSorted
This commit is contained in:
OLEGSHA 2020-11-17 12:46:33 +03:00
parent b51b3a4d80
commit 5d7cfdb3bc
62 changed files with 635 additions and 303 deletions

View File

@ -66,6 +66,18 @@ public class ArrayUtil {
return -1; return -1;
} }
public static boolean isSorted(byte[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
if ((array[i] < array[i + 1]) != ascending) {
return false;
}
}
return true;
}
public static int firstIndexOf(short[] array, short element) { public static int firstIndexOf(short[] array, short element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (array[i] == element) { if (array[i] == element) {
@ -107,6 +119,18 @@ public class ArrayUtil {
return -1; return -1;
} }
public static boolean isSorted(short[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
if ((array[i] < array[i + 1]) != ascending) {
return false;
}
}
return true;
}
public static int firstIndexOf(int[] array, int element) { public static int firstIndexOf(int[] array, int element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (array[i] == element) { if (array[i] == element) {
@ -148,6 +172,18 @@ public class ArrayUtil {
return -1; return -1;
} }
public static boolean isSorted(int[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
if ((array[i] < array[i + 1]) != ascending) {
return false;
}
}
return true;
}
public static int firstIndexOf(long[] array, long element) { public static int firstIndexOf(long[] array, long element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (array[i] == element) { if (array[i] == element) {
@ -189,6 +225,18 @@ public class ArrayUtil {
return -1; return -1;
} }
public static boolean isSorted(long[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
if ((array[i] < array[i + 1]) != ascending) {
return false;
}
}
return true;
}
public static int firstIndexOf(float[] array, float element) { public static int firstIndexOf(float[] array, float element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (array[i] == element) { if (array[i] == element) {
@ -230,6 +278,18 @@ public class ArrayUtil {
return -1; return -1;
} }
public static boolean isSorted(float[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
if ((array[i] < array[i + 1]) != ascending) {
return false;
}
}
return true;
}
public static int firstIndexOf(double[] array, double element) { public static int firstIndexOf(double[] array, double element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (array[i] == element) { if (array[i] == element) {
@ -271,6 +331,18 @@ public class ArrayUtil {
return -1; return -1;
} }
public static boolean isSorted(double[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
if ((array[i] < array[i + 1]) != ascending) {
return false;
}
}
return true;
}
public static int firstIndexOf(boolean[] array, boolean element) { public static int firstIndexOf(boolean[] array, boolean element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (array[i] == element) { if (array[i] == element) {
@ -340,6 +412,18 @@ public class ArrayUtil {
return -1; return -1;
} }
public static boolean isSorted(char[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
if ((array[i] < array[i + 1]) != ascending) {
return false;
}
}
return true;
}
public static int firstIndexOf(Object[] array, Object element) { public static int firstIndexOf(Object[] array, Object element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (array[i] == element) { if (array[i] == element) {
@ -422,6 +506,20 @@ public class ArrayUtil {
return -1; return -1;
} }
public static <T extends Comparable<T>> boolean isSorted(T[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue;
int order = array[i].compareTo(array[i + 1]);
if ((order < 0) != ascending) {
return false;
}
}
return true;
}
public static long sum(byte[] array, int start, int length) { public static long sum(byte[] array, int start, int length) {
long s = 0; long s = 0;
length += start; length += start;

View File

@ -29,6 +29,8 @@ import java.util.Iterator;
import java.util.Objects; import java.util.Objects;
import java.util.function.IntFunction; import java.util.function.IntFunction;
import ru.windcorp.jputil.ArrayUtil;
public class StringUtil { public class StringUtil {
private StringUtil() {} private StringUtil() {}
@ -369,6 +371,106 @@ public class StringUtil {
return result; return result;
} }
/**
* Splits {@code src} at index {@code at} discarding the character at that index.
* <p>
* Indices {@code 0} and {@code src.length() - 1} produce {@code str} excluding
* the specified character and {@code ""}.
* <p>
* @param src the String to split
* @param at index to split at
* @throws IllegalArgumentException if the index is out of bounds for {@code src}
* @return an array containing the substrings, in order of encounter in {@code src}.
* Its length is always 2.
*/
public static String[] splitAt(String src, int at) {
Objects.requireNonNull(src, "src");
if (at < 0) {
throw new StringIndexOutOfBoundsException(at);
} else if (at >= src.length()) {
throw new StringIndexOutOfBoundsException(at);
}
if (at == 0) {
return new String[] {"", src.substring(1)};
} else if (at == src.length()) {
return new String[] {src.substring(0, src.length() - 1), ""};
}
return new String[] {
src.substring(0, at),
src.substring(at + 1)
};
}
/**
* Splits {@code src} at indices {@code at} discarding characters at those indices.
* <p>
* Indices {@code 0} and {@code src.length() - 1} produce extra zero-length outputs.
* Duplicate indices produce extra zero-length outputs.
* <p>
* Examples:
* <pre>
* splitAt("a.b.c", new int[] {1, 3}) -> {"a", "b", "c"}
* splitAt("a..b", new int[] {1, 2}) -> {"a", "", "b"}
* splitAt(".b.", new int[] {0, 2}) -> {"", "b", ""}
* splitAt("a.b", new int[] {1, 1, 1}) -> {"a", "", "", "b"}
* </pre>
* @param src the String to split
* @param at indices to split at, in any order
* @throws IllegalArgumentException if some index is out of bounds for {@code src}
* @return an array containing the substrings, in order of encounter in {@code src}.
* Its length is always {@code at.length + 1}.
*/
public static String[] splitAt(String src, int... at) {
Objects.requireNonNull(src, "src");
Objects.requireNonNull(at, "at");
if (at.length == 0) return new String[] {src};
if (at.length == 1) return splitAt(src, at[0]);
int[] indices; // Always sorted
if (ArrayUtil.isSorted(at, true)) {
indices = at;
} else {
indices = at.clone();
Arrays.sort(indices);
}
if (indices[0] < 0) {
throw new StringIndexOutOfBoundsException(indices[0]);
} else if (indices[indices.length - 1] >= src.length()) {
throw new StringIndexOutOfBoundsException(indices[indices.length - 1]);
}
String[] result = new String[at.length + 1];
int start = 0;
int resultIndex = 0;
for (int index : indices) {
int end = index;
String substring;
if (end <= start) {
// Duplicate or successive index
substring = "";
} else {
substring = src.substring(start, end);
}
result[resultIndex] = substring;
resultIndex++;
start = end + 1;
}
result[resultIndex] = src.substring(start);
return result;
}
private static IllegalArgumentException illegalArrayLength(int length) { private static IllegalArgumentException illegalArrayLength(int length) {
return new IllegalArgumentException("arrayLength must be non-negative (" + length + ")"); return new IllegalArgumentException("arrayLength must be non-negative (" + length + ")");
} }

View File

@ -1,11 +1,11 @@
package ru.windcorp.progressia.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public abstract class ControlTrigger extends Namespaced { public abstract class ControlTrigger extends Namespaced {
public ControlTrigger(String namespace, String name) { public ControlTrigger(String id) {
super(namespace, name); super(id);
} }
} }

View File

@ -5,8 +5,8 @@ import ru.windcorp.progressia.common.comms.controls.PacketControl;
public abstract class ControlTriggerInputBased extends ControlTrigger { public abstract class ControlTriggerInputBased extends ControlTrigger {
public ControlTriggerInputBased(String namespace, String name) { public ControlTriggerInputBased(String id) {
super(namespace, name); super(id);
} }
public abstract PacketControl onInputEvent(InputEvent event); public abstract PacketControl onInputEvent(InputEvent event);

View File

@ -6,6 +6,7 @@ import ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent;
import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry; import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry;
import ru.windcorp.progressia.common.comms.controls.PacketControl; import ru.windcorp.progressia.common.comms.controls.PacketControl;
import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil;
public class ControlTriggerOnKeyPress extends ControlTriggerInputBased { public class ControlTriggerOnKeyPress extends ControlTriggerInputBased {
@ -13,13 +14,13 @@ public class ControlTriggerOnKeyPress extends ControlTriggerInputBased {
private final PacketControl packet; private final PacketControl packet;
public ControlTriggerOnKeyPress( public ControlTriggerOnKeyPress(
String namespace, String name, String id,
Predicate<KeyEvent> predicate Predicate<KeyEvent> predicate
) { ) {
super(namespace, name); super(id);
this.predicate = predicate; this.predicate = predicate;
this.packet = new PacketControl( this.packet = new PacketControl(
getNamespace(), "ControlKeyPress" + getName(), NamespacedUtil.getId(getNamespace(), "ControlKeyPress" + getName()),
ControlDataRegistry.getInstance().get(getId()) ControlDataRegistry.getInstance().get(getId())
); );
} }

View File

@ -1,6 +1,6 @@
package ru.windcorp.progressia.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class ControlTriggerRegistry extends NamespacedRegistry<ControlTrigger> { public class ControlTriggerRegistry extends NamespacedRegistry<ControlTrigger> {

View File

@ -18,13 +18,13 @@
package ru.windcorp.progressia.client.world.block; package ru.windcorp.progressia.client.world.block;
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.common.util.Namespaced;
public abstract class BlockRender extends Namespaced { public abstract class BlockRender extends Namespaced {
public BlockRender(String namespace, String name) { public BlockRender(String id) {
super(namespace, name); super(id);
} }
public void render(ShapeRenderHelper renderer) { public void render(ShapeRenderHelper renderer) {

View File

@ -22,8 +22,8 @@ import ru.windcorp.progressia.client.graphics.model.Renderable;
public class BlockRenderNone extends BlockRender { public class BlockRenderNone extends BlockRender {
public BlockRenderNone(String namespace, String name) { public BlockRenderNone(String id) {
super(namespace, name); super(id);
} }
@Override @Override

View File

@ -23,25 +23,22 @@ import ru.windcorp.progressia.common.world.block.BlockFace;
public class BlockRenderOpaqueCube extends BlockRenderTexturedCube { public class BlockRenderOpaqueCube extends BlockRenderTexturedCube {
public BlockRenderOpaqueCube( public BlockRenderOpaqueCube(
String namespace, String name, String id,
Texture topTexture, Texture bottomTexture, Texture topTexture, Texture bottomTexture,
Texture northTexture, Texture southTexture, Texture northTexture, Texture southTexture,
Texture eastTexture, Texture westTexture Texture eastTexture, Texture westTexture
) { ) {
super( super(
namespace, name, id,
topTexture, bottomTexture, topTexture, bottomTexture,
northTexture, southTexture, northTexture, southTexture,
eastTexture, westTexture eastTexture, westTexture
); );
} }
public BlockRenderOpaqueCube( public BlockRenderOpaqueCube(String id, Texture texture) {
String namespace, String name,
Texture texture
) {
this( this(
namespace, name, id,
texture, texture, texture, texture,
texture, texture, texture, texture,
texture, texture texture, texture

View File

@ -22,7 +22,7 @@ import ru.windcorp.progressia.client.graphics.texture.Atlases.AtlasGroup;
import ru.windcorp.progressia.client.graphics.texture.SimpleTexture; import ru.windcorp.progressia.client.graphics.texture.SimpleTexture;
import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.resource.ResourceManager;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class BlockRenderRegistry extends NamespacedRegistry<BlockRender> { public class BlockRenderRegistry extends NamespacedRegistry<BlockRender> {

View File

@ -36,12 +36,12 @@ implements OpaqueCube {
private final Map<BlockFace, Texture> textures = new HashMap<>(); private final Map<BlockFace, Texture> textures = new HashMap<>();
public BlockRenderTexturedCube( public BlockRenderTexturedCube(
String namespace, String name, String id,
Texture topTexture, Texture bottomTexture, Texture topTexture, Texture bottomTexture,
Texture northTexture, Texture southTexture, Texture northTexture, Texture southTexture,
Texture eastTexture, Texture westTexture Texture eastTexture, Texture westTexture
) { ) {
super(namespace, name); super(id);
textures.put(TOP, topTexture); textures.put(TOP, topTexture);
textures.put(BOTTOM, bottomTexture); textures.put(BOTTOM, bottomTexture);

View File

@ -23,25 +23,22 @@ import ru.windcorp.progressia.common.world.block.BlockFace;
public class BlockRenderTransparentCube extends BlockRenderTexturedCube { public class BlockRenderTransparentCube extends BlockRenderTexturedCube {
public BlockRenderTransparentCube( public BlockRenderTransparentCube(
String namespace, String name, String id,
Texture topTexture, Texture bottomTexture, Texture topTexture, Texture bottomTexture,
Texture northTexture, Texture southTexture, Texture northTexture, Texture southTexture,
Texture eastTexture, Texture westTexture Texture eastTexture, Texture westTexture
) { ) {
super( super(
namespace, name, id,
topTexture, bottomTexture, topTexture, bottomTexture,
northTexture, southTexture, northTexture, southTexture,
eastTexture, westTexture eastTexture, westTexture
); );
} }
public BlockRenderTransparentCube( public BlockRenderTransparentCube(String id, Texture texture) {
String namespace, String name,
Texture texture
) {
this( this(
namespace, name, id,
texture, texture, texture, texture,
texture, texture, texture, texture,
texture, texture texture, texture

View File

@ -19,21 +19,21 @@ package ru.windcorp.progressia.client.world.cro;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public abstract class ChunkRenderOptimizerSupplier extends Namespaced { public abstract class ChunkRenderOptimizerSupplier extends Namespaced {
public ChunkRenderOptimizerSupplier(String namespace, String name) { public ChunkRenderOptimizerSupplier(String id) {
super(namespace, name); super(id);
} }
public abstract ChunkRenderOptimizer createOptimizer(); public abstract ChunkRenderOptimizer createOptimizer();
public static ChunkRenderOptimizerSupplier of( public static ChunkRenderOptimizerSupplier of(
String namespace, String name, String id,
Supplier<ChunkRenderOptimizer> supplier Supplier<ChunkRenderOptimizer> supplier
) { ) {
return new ChunkRenderOptimizerSupplier(namespace, name) { return new ChunkRenderOptimizerSupplier(id) {
@Override @Override
public ChunkRenderOptimizer createOptimizer() { public ChunkRenderOptimizer createOptimizer() {
return supplier.get(); return supplier.get();

View File

@ -30,7 +30,7 @@ public class ChunkRenderOptimizers {
static { static {
register(ChunkRenderOptimizerSupplier.of( register(ChunkRenderOptimizerSupplier.of(
"Default", "OpaqueCube", "Default:OpaqueCube",
ChunkRenderOptimizerCube::new ChunkRenderOptimizerCube::new
)); ));
} }

View File

@ -1,12 +1,12 @@
package ru.windcorp.progressia.client.world.entity; package ru.windcorp.progressia.client.world.entity;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
public abstract class EntityRender extends Namespaced { public abstract class EntityRender extends Namespaced {
public EntityRender(String namespace, String name) { public EntityRender(String id) {
super(namespace, name); super(id);
} }
public abstract EntityRenderable createRenderable(EntityData entity); public abstract EntityRenderable createRenderable(EntityData entity);

View File

@ -6,7 +6,7 @@ import ru.windcorp.progressia.client.graphics.texture.TextureLoader;
import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive; import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive;
import ru.windcorp.progressia.client.graphics.texture.TextureSettings; import ru.windcorp.progressia.client.graphics.texture.TextureSettings;
import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.resource.ResourceManager;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class EntityRenderRegistry extends NamespacedRegistry<EntityRender> { public class EntityRenderRegistry extends NamespacedRegistry<EntityRender> {

View File

@ -3,13 +3,13 @@ package ru.windcorp.progressia.client.world.tile;
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizer; import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizer;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.block.BlockFace; import ru.windcorp.progressia.common.world.block.BlockFace;
public class TileRender extends Namespaced { public class TileRender extends Namespaced {
public TileRender(String namespace, String name) { public TileRender(String id) {
super(namespace, name); super(id);
} }
public void render(ShapeRenderHelper renderer, BlockFace face) { public void render(ShapeRenderHelper renderer, BlockFace face) {

View File

@ -18,10 +18,10 @@ public class TileRenderGrass extends TileRender implements OpaqueTile {
private final Texture sideTexture; private final Texture sideTexture;
public TileRenderGrass( public TileRenderGrass(
String namespace, String name, String id,
Texture top, Texture side Texture top, Texture side
) { ) {
super(namespace, name); super(id);
this.topTexture = top; this.topTexture = top;
this.sideTexture = side; this.sideTexture = side;
} }

View File

@ -22,7 +22,7 @@ import ru.windcorp.progressia.client.graphics.texture.Atlases.AtlasGroup;
import ru.windcorp.progressia.client.graphics.texture.SimpleTexture; import ru.windcorp.progressia.client.graphics.texture.SimpleTexture;
import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.resource.ResourceManager;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class TileRenderRegistry extends NamespacedRegistry<TileRender> { public class TileRenderRegistry extends NamespacedRegistry<TileRender> {

View File

@ -16,8 +16,8 @@ public class TileRenderSimple extends TileRender implements OpaqueTile {
private final Texture texture; private final Texture texture;
public TileRenderSimple(String namespace, String name, Texture texture) { public TileRenderSimple(String id, Texture texture) {
super(namespace, name); super(id);
this.texture = texture; this.texture = texture;
} }

View File

@ -1,11 +1,11 @@
package ru.windcorp.progressia.common.comms.controls; package ru.windcorp.progressia.common.comms.controls;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class ControlData extends Namespaced { public class ControlData extends Namespaced {
public ControlData(String namespace, String name) { public ControlData(String id) {
super(namespace, name); super(id);
} }
} }

View File

@ -1,6 +1,6 @@
package ru.windcorp.progressia.common.comms.controls; package ru.windcorp.progressia.common.comms.controls;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class ControlDataRegistry extends NamespacedRegistry<ControlData> { public class ControlDataRegistry extends NamespacedRegistry<ControlData> {

View File

@ -6,8 +6,8 @@ public class PacketControl extends Packet {
private final ControlData control; private final ControlData control;
public PacketControl(String namespace, String name, ControlData control) { public PacketControl(String id, ControlData control) {
super(namespace, name); super(id);
this.control = control; this.control = control;
} }

View File

@ -1,11 +1,11 @@
package ru.windcorp.progressia.common.comms.packets; package ru.windcorp.progressia.common.comms.packets;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class Packet extends Namespaced { public class Packet extends Namespaced {
public Packet(String namespace, String name) { public Packet(String id) {
super(namespace, name); super(id);
} }
} }

View File

@ -5,7 +5,11 @@ public class PacketSetLocalPlayer extends Packet {
private long localPlayerEntityId; private long localPlayerEntityId;
public PacketSetLocalPlayer(long entityId) { public PacketSetLocalPlayer(long entityId) {
super("Core", "SetLocalPlayer"); this("Core:SetLocalPlayer", entityId);
}
protected PacketSetLocalPlayer(String id, long entityId) {
super(id);
this.localPlayerEntityId = entityId; this.localPlayerEntityId = entityId;
} }

View File

@ -4,8 +4,8 @@ import ru.windcorp.progressia.common.world.WorldData;
public abstract class PacketWorldChange extends Packet { public abstract class PacketWorldChange extends Packet {
public PacketWorldChange(String namespace, String name) { public PacketWorldChange(String id) {
super(namespace, name); super(id);
} }
public abstract void apply(WorldData world); public abstract void apply(WorldData world);

View File

@ -43,10 +43,8 @@ extends AbstractStatefulObjectLayout {
} }
@Override @Override
public StateFieldBuilder getBuilder(String namespace, String name) { public StateFieldBuilder getBuilder(String id) {
return new InspectingStateFieldBuilder( return new InspectingStateFieldBuilder(id);
namespace, name
);
} }
private class InspectingStateFieldBuilder implements StateFieldBuilder { private class InspectingStateFieldBuilder implements StateFieldBuilder {
@ -56,7 +54,7 @@ extends AbstractStatefulObjectLayout {
@Override @Override
public IntStateField build() { public IntStateField build() {
return registerField(new IntStateField( return registerField(new IntStateField(
namespace, name, id,
isLocal, isLocal,
fieldIndexCounters.getIntsThenIncrement() fieldIndexCounters.getIntsThenIncrement()
)); ));
@ -64,16 +62,12 @@ extends AbstractStatefulObjectLayout {
} }
private final String namespace; private final String id;
private final String name;
private boolean isLocal = true; private boolean isLocal = true;
public InspectingStateFieldBuilder( public InspectingStateFieldBuilder(String id) {
String namespace, String name this.id = id;
) {
this.namespace = namespace;
this.name = name;
} }
@Override @Override

View File

@ -7,11 +7,11 @@ import java.io.IOException;
public class IntStateField extends StateField { public class IntStateField extends StateField {
public IntStateField( public IntStateField(
String namespace, String name, String id,
boolean isLocal, boolean isLocal,
int index int index
) { ) {
super(namespace, name, isLocal, index); super(id, isLocal, index);
} }
public int get(StatefulObject object) { public int get(StatefulObject object) {

View File

@ -35,7 +35,7 @@ extends AbstractStatefulObjectLayout {
} }
@Override @Override
public StateFieldBuilder getBuilder(String namespace, String name) { public StateFieldBuilder getBuilder(String id) {
return new RetrieverStateFieldBuilder(); return new RetrieverStateFieldBuilder();
} }

View File

@ -4,7 +4,7 @@ import java.io.DataInput;
import java.io.DataOutput; import java.io.DataOutput;
import java.io.IOException; import java.io.IOException;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public abstract class StateField extends Namespaced { public abstract class StateField extends Namespaced {
@ -12,11 +12,11 @@ public abstract class StateField extends Namespaced {
private final int index; private final int index;
public StateField( public StateField(
String namespace, String name, String id,
boolean isLocal, boolean isLocal,
int index int index
) { ) {
super(namespace, name); super(id);
this.isLocal = isLocal; this.isLocal = isLocal;
this.index = index; this.index = index;
} }

View File

@ -5,7 +5,7 @@ import java.io.DataOutput;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
/** /**
* An abstract class describing objects that have trackable state, * An abstract class describing objects that have trackable state,
@ -44,10 +44,9 @@ public abstract class StatefulObject extends Namespaced {
public StatefulObject( public StatefulObject(
StatefulObjectRegistry<?> type, StatefulObjectRegistry<?> type,
String namespace, String id
String name
) { ) {
super(namespace, name); super(id);
this.layout = type.getLayout(getId()); this.layout = type.getLayout(getId());
this.storage = getLayout().createStorage(); this.storage = getLayout().createStorage();
} }
@ -96,8 +95,8 @@ public abstract class StatefulObject extends Namespaced {
* *
* @return a configured builder * @return a configured builder
*/ */
protected StateFieldBuilder field(String namespace, String name) { protected StateFieldBuilder field(String id) {
StateFieldBuilder builder = getLayout().getBuilder(namespace, name); StateFieldBuilder builder = getLayout().getBuilder(id);
builder.setOrdinal(fieldOrdinal); builder.setOrdinal(fieldOrdinal);
fieldOrdinal++; fieldOrdinal++;

View File

@ -43,6 +43,6 @@ public abstract class StatefulObjectLayout {
public abstract int computeHashCode(StatefulObject object); public abstract int computeHashCode(StatefulObject object);
public abstract boolean areEqual(StatefulObject a, StatefulObject b); public abstract boolean areEqual(StatefulObject a, StatefulObject b);
public abstract StateFieldBuilder getBuilder(String namespace, String name); public abstract StateFieldBuilder getBuilder(String id);
} }

View File

@ -5,8 +5,8 @@ import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
/** /**
* Registry-like object for identification of various {@link StatefulObject} * Registry-like object for identification of various {@link StatefulObject}
@ -30,8 +30,8 @@ public class StatefulObjectRegistry<T extends StatefulObject> {
private final AtomicBoolean isRegistered = new AtomicBoolean(false); private final AtomicBoolean isRegistered = new AtomicBoolean(false);
public Type(String namespace, String name, Factory<T> factory) { public Type(String id, Factory<T> factory) {
super(namespace, name); super(id);
this.factory = factory; this.factory = factory;
} }
@ -91,8 +91,8 @@ public class StatefulObjectRegistry<T extends StatefulObject> {
return registry.get(id).build(); return registry.get(id).build();
} }
public void register(String namespace, String name, Factory<T> factory) { public void register(String id, Factory<T> factory) {
registry.register(new Type<>(namespace, name, factory)); registry.register(new Type<>(id, factory));
} }
} }

View File

@ -1,46 +0,0 @@
package ru.windcorp.progressia.common.util;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.regex.Pattern;
public class NamespacedUtil {
public static final char SEPARATOR = ':';
public static final int MAX_PART_LENGTH = 127;
public static final int MAX_TOTAL_LENGTH = MAX_PART_LENGTH * 2 + 1;
private static final String PART_REGEX = "^[A-Z][a-zA-Z0-9]{2,}$";
private static final Predicate<String> PART_CHECKER =
Pattern.compile(PART_REGEX).asPredicate();
public static String getId(String namespace, String name) {
checkPart(namespace, "Namespace");
checkPart(name, "Name");
return namespace + SEPARATOR + name;
}
private static void checkPart(String data, String name) {
Objects.requireNonNull(data, name);
if (data.length() > MAX_PART_LENGTH) {
throw new IllegalArgumentException(
name + " \"" + data + "\" is too long. "
+ "Expected at most " + MAX_PART_LENGTH
+ " characters"
);
}
if (!PART_CHECKER.test(name)) {
throw new IllegalArgumentException(
name + " \"" + data + "\" is invalid. "
+ "Allowed is: " + PART_REGEX
);
}
}
private NamespacedUtil() {}
}

View File

@ -0,0 +1,27 @@
package ru.windcorp.progressia.common.util.namespaces;
public class IllegalIdException extends RuntimeException {
private static final long serialVersionUID = -1572240191058305981L;
public IllegalIdException() {
super();
}
protected IllegalIdException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public IllegalIdException(String message, Throwable cause) {
super(message, cause);
}
public IllegalIdException(String message) {
super(message);
}
public IllegalIdException(Throwable cause) {
super(cause);
}
}

View File

@ -15,50 +15,27 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.common.util; package ru.windcorp.progressia.common.util.namespaces;
import java.util.Objects; public abstract class Namespaced {
import java.util.function.Predicate;
import java.util.regex.Pattern;
public abstract class Namespaced extends Named {
private static final char SEPARATOR = ':';
private static final String PART_REGEX = "^[A-Z][a-zA-Z0-9]{2,}$";
private static final Predicate<String> PART_CHECKER =
Pattern.compile(PART_REGEX).asPredicate();
private final String namespace;
private final String id; private final String id;
public Namespaced(String namespace, String name) { public Namespaced(String id) {
super(name); NamespacedUtil.checkId(id);
this.namespace = Objects.requireNonNull(namespace, "namespace"); this.id = id;
this.id = namespace + SEPARATOR + name;
if (!PART_CHECKER.test(name)) {
throw new IllegalArgumentException(
"Name \"" + name + "\" is invalid. "
+ "Allowed is: " + PART_REGEX
);
}
if (!PART_CHECKER.test(namespace)) {
throw new IllegalArgumentException(
"Namespace \"" + namespace + "\" is invalid. "
+ "Allowed is: " + PART_REGEX
);
}
} }
public String getId() { public final String getId() {
return id; return id;
} }
public String getNamespace() { public String getNamespace() {
return namespace; return NamespacedUtil.getNamespace(getId());
}
public String getName() {
return NamespacedUtil.getName(getId());
} }
@Override @Override
@ -75,15 +52,10 @@ public abstract class Namespaced extends Named {
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) if (this == obj)
return true; return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
Namespaced other = (Namespaced) obj; Namespaced other = (Namespaced) obj;
if (id == null) { if (!id.equals(other.id))
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false; return false;
return true; return true;
} }

View File

@ -1,4 +1,4 @@
package ru.windcorp.progressia.common.util; package ru.windcorp.progressia.common.util.namespaces;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;

View File

@ -0,0 +1,106 @@
package ru.windcorp.progressia.common.util.namespaces;
import java.util.Objects;
import ru.windcorp.jputil.chars.StringUtil;
public class NamespacedUtil {
public static final char SEPARATOR = ':';
public static final int MAX_ID_LENGTH = 255;
private static final int MAX_PART_LENGTH = (MAX_ID_LENGTH - 1) / 2;
public static final int MAX_NAMESPACE_LENGTH = MAX_PART_LENGTH;
public static final int MAX_NAME_LENGTH = MAX_PART_LENGTH;
private static final int MIN_PART_LENGTH = 3;
public static final int MIN_NAMESPACE_LENGTH = MIN_PART_LENGTH;
public static final int MIN_NAME_LENGTH = MIN_PART_LENGTH;
/*
* This is the definition of the accepted pattern, but the value of
* these constants is not actually consulted in the check* methods.
*/
private static final String PART_CORE_REGEX = "[A-Z][a-zA-Z0-9]{2," + (MAX_PART_LENGTH - 1) + "}";
private static final String PART_REGEX = "^" + PART_CORE_REGEX + "$";
public static final String NAMESPACE_REGEX = PART_REGEX;
public static final String NAME_REGEX = PART_REGEX;
public static final String ID_REGEX = "^" + PART_CORE_REGEX + ":" + PART_CORE_REGEX + "$";
public static String getName(String id) {
checkId(id);
return id.substring(id.indexOf(':') + 1);
}
public static String getNamespace(String id) {
checkId(id);
return id.substring(0, id.indexOf(':'));
}
public static String getId(String namespace, String name) {
checkPart(namespace, 0, namespace.length(), "Namespace");
checkPart(name, 0, name.length(), "Name");
return namespace + SEPARATOR + name;
}
public static void checkId(String id) {
Objects.requireNonNull(id, "id");
int firstSeparator = id.indexOf(SEPARATOR);
boolean areSeparatorsInvalid = (firstSeparator < 0) || (id.indexOf(SEPARATOR, firstSeparator + 1) >= 0);
if (areSeparatorsInvalid) {
int separators = StringUtil.count(id, SEPARATOR);
throw new IllegalIdException(
"ID \"" + id + "\" is invalid. "
+ (separators == 0 ? "No " : "Too many (" + separators + ") ")
+ "separators '" + SEPARATOR + "' found, exactly one required"
);
}
checkPart(id, 0, firstSeparator, "namespace");
checkPart(id, firstSeparator + 1, id.length() - firstSeparator - 1, "name");
}
private static void checkPart(String data, int offset, int length, String nameForErrors) {
Objects.requireNonNull(data, nameForErrors);
if (length > MAX_PART_LENGTH) {
throw new IllegalIdException(
nameForErrors + " \"" + data.substring(offset, offset + length) + "\" is too long. "
+ "Expected at most " + MAX_PART_LENGTH
+ " characters"
);
} else if (length < MIN_PART_LENGTH) {
throw new IllegalIdException(
nameForErrors + " \"" + data.substring(offset, offset + length) + "\" is too short. "
+ "Expected at lest " + MIN_PART_LENGTH
+ " characters"
);
}
// Don't actually use *_REGEX for speed
for (int i = 0; i < length; ++i) {
char c = data.charAt(i + offset);
if (!(
( c >= 'A' && c <= 'Z') ||
(i != 0 && c >= 'a' && c <= 'z') ||
(i != 0 && c >= '0' && c <= '9')
)) {
throw new IllegalIdException(
nameForErrors + " \"" + data.substring(offset, offset + length) + "\" is invalid. "
+ "Allowed is: " + PART_REGEX
);
}
}
}
private NamespacedUtil() {}
}

View File

@ -19,12 +19,12 @@ package ru.windcorp.progressia.common.world.block;
import ru.windcorp.progressia.common.collision.AABB; import ru.windcorp.progressia.common.collision.AABB;
import ru.windcorp.progressia.common.collision.CollisionModel; import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class BlockData extends Namespaced { public class BlockData extends Namespaced {
public BlockData(String namespace, String name) { public BlockData(String id) {
super(namespace, name); super(id);
} }
public CollisionModel getCollisionModel() { public CollisionModel getCollisionModel() {

View File

@ -17,7 +17,7 @@
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.common.world.block; package ru.windcorp.progressia.common.world.block;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class BlockDataRegistry extends NamespacedRegistry<BlockData> { public class BlockDataRegistry extends NamespacedRegistry<BlockData> {

View File

@ -20,8 +20,8 @@ public class EntityData extends StatefulObject implements Collideable {
private double age = 0; private double age = 0;
public EntityData(String namespace, String name) { public EntityData(String id) {
super(EntityDataRegistry.getInstance(), namespace, name); super(EntityDataRegistry.getInstance(), id);
} }
public Vec3 getPosition() { public Vec3 getPosition() {

View File

@ -10,8 +10,8 @@ public class EntityDataRegistry extends StatefulObjectRegistry<EntityData> {
return INSTANCE; return INSTANCE;
} }
public void register(String namespace, String name) { public void register(String id) {
super.register(namespace, name, () -> new EntityData(namespace, name)); super.register(id, () -> new EntityData(id));
} }
} }

View File

@ -15,7 +15,11 @@ public class PacketEntityChange extends PacketWorldChange {
private final DataBuffer buffer = new DataBuffer(); private final DataBuffer buffer = new DataBuffer();
public PacketEntityChange() { public PacketEntityChange() {
super("Core", "EntityChange"); super("Core:EntityChange");
}
protected PacketEntityChange(String id) {
super(id);
} }
public long getEntityId() { public long getEntityId() {

View File

@ -17,12 +17,12 @@
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.common.world.tile; package ru.windcorp.progressia.common.world.tile;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class TileData extends Namespaced { public class TileData extends Namespaced {
public TileData(String namespace, String name) { public TileData(String id) {
super(namespace, name); super(id);
} }
} }

View File

@ -17,7 +17,7 @@
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.common.world.tile; package ru.windcorp.progressia.common.world.tile;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class TileDataRegistry extends NamespacedRegistry<TileData> { public class TileDataRegistry extends NamespacedRegistry<TileData> {

View File

@ -1,14 +1,14 @@
package ru.windcorp.progressia.server.comms.controls; package ru.windcorp.progressia.server.comms.controls;
import ru.windcorp.progressia.common.comms.controls.PacketControl; import ru.windcorp.progressia.common.comms.controls.PacketControl;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.comms.Client; import ru.windcorp.progressia.server.comms.Client;
public abstract class ControlLogic extends Namespaced { public abstract class ControlLogic extends Namespaced {
public ControlLogic(String namespace, String name) { public ControlLogic(String id) {
super(namespace, name); super(id);
} }
public abstract void apply( public abstract void apply(

View File

@ -1,6 +1,6 @@
package ru.windcorp.progressia.server.comms.controls; package ru.windcorp.progressia.server.comms.controls;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class ControlLogicRegistry extends NamespacedRegistry<ControlLogic> { public class ControlLogicRegistry extends NamespacedRegistry<ControlLogic> {

View File

@ -35,7 +35,11 @@ public class ImplementedChangeTracker implements Changer {
private BlockData block; private BlockData block;
public SetBlock() { public SetBlock() {
super("Core", "SetBlock"); this("Core:SetBlock");
}
protected SetBlock(String id) {
super(id);
} }
public void initialize(Vec3i position, BlockData block) { public void initialize(Vec3i position, BlockData block) {
@ -76,7 +80,11 @@ public class ImplementedChangeTracker implements Changer {
private boolean shouldAdd; private boolean shouldAdd;
public AddOrRemoveTile() { public AddOrRemoveTile() {
super("Core", "AddOrRemoveTile"); this("Core:AddOrRemoveTile");
}
protected AddOrRemoveTile(String id) {
super(id);
} }
public void initialize( public void initialize(

View File

@ -1,11 +1,11 @@
package ru.windcorp.progressia.server.world.block; package ru.windcorp.progressia.server.world.block;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class BlockLogic extends Namespaced { public class BlockLogic extends Namespaced {
public BlockLogic(String namespace, String name) { public BlockLogic(String id) {
super(namespace, name); super(id);
} }
} }

View File

@ -1,6 +1,6 @@
package ru.windcorp.progressia.server.world.block; package ru.windcorp.progressia.server.world.block;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class BlockLogicRegistry extends NamespacedRegistry<BlockLogic> { public class BlockLogicRegistry extends NamespacedRegistry<BlockLogic> {

View File

@ -1,14 +1,14 @@
package ru.windcorp.progressia.server.world.entity; package ru.windcorp.progressia.server.world.entity;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.server.world.Changer; import ru.windcorp.progressia.server.world.Changer;
import ru.windcorp.progressia.server.world.TickContext; import ru.windcorp.progressia.server.world.TickContext;
public class EntityLogic extends Namespaced { public class EntityLogic extends Namespaced {
public EntityLogic(String namespace, String name) { public EntityLogic(String id) {
super(namespace, name); super(id);
} }
public void tick(EntityData entity, TickContext context, Changer changer) { public void tick(EntityData entity, TickContext context, Changer changer) {

View File

@ -1,6 +1,6 @@
package ru.windcorp.progressia.server.world.entity; package ru.windcorp.progressia.server.world.entity;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class EntityLogicRegistry extends NamespacedRegistry<EntityLogic> { public class EntityLogicRegistry extends NamespacedRegistry<EntityLogic> {

View File

@ -1,12 +1,12 @@
package ru.windcorp.progressia.server.world.tile; package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.block.BlockFace; import ru.windcorp.progressia.common.world.block.BlockFace;
public class TileLogic extends Namespaced { public class TileLogic extends Namespaced {
public TileLogic(String namespace, String name) { public TileLogic(String id) {
super(namespace, name); super(id);
} }
public boolean canOccupyFace(TileTickContext context) { public boolean canOccupyFace(TileTickContext context) {

View File

@ -1,6 +1,6 @@
package ru.windcorp.progressia.server.world.tile; package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.util.NamespacedRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedRegistry;
public class TileLogicRegistry extends NamespacedRegistry<TileLogic> { public class TileLogicRegistry extends NamespacedRegistry<TileLogic> {

View File

@ -42,65 +42,65 @@ public class TestContent {
} }
private static void registerBlocks() { private static void registerBlocks() {
register(new BlockData("Test", "Air") { register(new BlockData("Test:Air") {
@Override @Override
public CollisionModel getCollisionModel() { public CollisionModel getCollisionModel() {
return null; return null;
} }
}); });
register(new BlockRenderNone("Test", "Air")); register(new BlockRenderNone("Test:Air"));
register(new BlockLogic("Test", "Air")); register(new BlockLogic("Test:Air"));
register(new BlockData("Test", "Dirt")); register(new BlockData("Test:Dirt"));
register(new BlockRenderOpaqueCube("Test", "Dirt", getBlockTexture("dirt"))); register(new BlockRenderOpaqueCube("Test:Dirt", getBlockTexture("dirt")));
register(new BlockLogic("Test", "Dirt")); register(new BlockLogic("Test:Dirt"));
register(new BlockData("Test", "Stone")); register(new BlockData("Test:Stone"));
register(new BlockRenderOpaqueCube("Test", "Stone", getBlockTexture("stone"))); register(new BlockRenderOpaqueCube("Test:Stone", getBlockTexture("stone")));
register(new BlockLogic("Test", "Stone")); register(new BlockLogic("Test:Stone"));
register(new BlockData("Test", "Compass")); register(new BlockData("Test:Compass"));
register(new BlockRenderOpaqueCube("Test", "Compass", getBlockTexture("compass"))); register(new BlockRenderOpaqueCube("Test:Compass", getBlockTexture("compass")));
register(new BlockLogic("Test", "Compass")); register(new BlockLogic("Test:Compass"));
register(new BlockData("Test", "Glass")); register(new BlockData("Test:Glass"));
register(new BlockRenderTransparentCube("Test", "Glass", getBlockTexture("glass_clear"))); register(new BlockRenderTransparentCube("Test:Glass", getBlockTexture("glass_clear")));
register(new BlockLogic("Test", "Glass")); register(new BlockLogic("Test:Glass"));
} }
private static void registerTiles() { private static void registerTiles() {
register(new TileData("Test", "Grass")); register(new TileData("Test:Grass"));
register(new TileRenderGrass("Test", "Grass", getTileTexture("grass_top"), getTileTexture("grass_side"))); register(new TileRenderGrass("Test:Grass", getTileTexture("grass_top"), getTileTexture("grass_side")));
register(new TileLogic("Test", "Grass")); register(new TileLogic("Test:Grass"));
register(new TileData("Test", "Stones")); register(new TileData("Test:Stones"));
register(new TileRenderSimple("Test", "Stones", getTileTexture("stones"))); register(new TileRenderSimple("Test:Stones", getTileTexture("stones")));
register(new TileLogic("Test", "Stones")); register(new TileLogic("Test:Stones"));
register(new TileData("Test", "YellowFlowers")); register(new TileData("Test:YellowFlowers"));
register(new TileRenderSimple("Test", "YellowFlowers", getTileTexture("yellow_flowers"))); register(new TileRenderSimple("Test:YellowFlowers", getTileTexture("yellow_flowers")));
register(new TileLogic("Test", "YellowFlowers")); register(new TileLogic("Test:YellowFlowers"));
register(new TileData("Test", "Sand")); register(new TileData("Test:Sand"));
register(new TileRenderSimple("Test", "Sand", getTileTexture("sand"))); register(new TileRenderSimple("Test:Sand", getTileTexture("sand")));
register(new TileLogic("Test", "Sand")); register(new TileLogic("Test:Sand"));
} }
private static void registerEntities() { private static void registerEntities() {
float scale = 1.8f / 8; float scale = 1.8f / 8;
registerEntityData("Test", "Player", e -> e.setCollisionModel(new AABB(0, 0, 4*scale, 0.75f, 0.75f, 1.8f))); registerEntityData("Test:Player", e -> e.setCollisionModel(new AABB(0, 0, 4*scale, 0.75f, 0.75f, 1.8f)));
register(new TestEntityRenderHuman()); register(new TestEntityRenderHuman("Test:Player"));
register(new EntityLogic("Test", "Player")); register(new EntityLogic("Test:Player"));
register("Test", "Statie", TestEntityDataStatie::new); register("Test:Statie", TestEntityDataStatie::new);
register(new TestEntityRenderStatie()); register(new TestEntityRenderStatie("Test:Statie"));
register(new TestEntityLogicStatie()); register(new TestEntityLogicStatie("Test:Statie"));
} }
private static void regsiterControls() { private static void regsiterControls() {
ControlDataRegistry.getInstance().register(new ControlData("Test", "Switch000")); ControlDataRegistry.getInstance().register(new ControlData("Test:Switch000"));
ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test", "Switch000", new KeyMatcher(GLFW.GLFW_KEY_H, new int[0], 0)::matches)); ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test:Switch000", new KeyMatcher(GLFW.GLFW_KEY_H, new int[0], 0)::matches));
ControlLogicRegistry.getInstance().register(new ControlLogic("Test", "Switch000") { ControlLogicRegistry.getInstance().register(new ControlLogic("Test:Switch000") {
@Override @Override
public void apply(Server server, PacketControl packet, Client client) { public void apply(Server server, PacketControl packet, Client client) {
Vec3i z000 = new Vec3i(0, 0, 0); Vec3i z000 = new Vec3i(0, 0, 0);
@ -111,32 +111,12 @@ public class TestContent {
if (data.getBlock(z000).getId().equals("Test:Stone")) { if (data.getBlock(z000).getId().equals("Test:Stone")) {
block = BlockDataRegistry.getInstance().get("Test:Glass"); block = BlockDataRegistry.getInstance().get("Test:Glass");
} else { } else {
block = BlockDataRegistry.getInstance().get("Test:Stone"); block = BlockDataRegistry.getInstance().get("Test:Stone");
} }
server.getAdHocChanger().setBlock(z000, block); server.getAdHocChanger().setBlock(z000, block);
} }
}); });
// ControlDataRegistry.getInstance().register(new ControlData("Test", "BreakBlock"));
// ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test", "BreakBlock", new KeyMatcher(GLFW.GLFW_KEY_ENTER, new int[0], 0)::matches));
// ControlLogicRegistry.getInstance().register(new ControlLogic("Test", "BreakBlock") {
// @Override
// public void apply(Server server, PacketControl packet, Client client) {
// Vec3i z000 = new Vec3i(0, 0, 0);
//
// ChunkData data = server.getWorld().getChunk(z000).getData();
//
// BlockData block;
// if (data.getBlock(z000).getId().equals("Test:Stone")) {
// block = BlockDataRegistry.getInstance().get("Test:Glass");
// } else {
// block = BlockDataRegistry.getInstance().get("Test:Stone");
// }
//
// server.getAdHocChanger().setBlock(z000, block);
// }
// });
} }
private static void register(BlockData x) { private static void register(BlockData x) {
@ -148,20 +128,20 @@ public class TestContent {
} }
private static void register( private static void register(
String namespace, String name, String id,
Factory<EntityData> factory Factory<EntityData> factory
) { ) {
EntityDataRegistry.getInstance().register(namespace, name, factory); EntityDataRegistry.getInstance().register(id, factory);
} }
private static void registerEntityData( private static void registerEntityData(
String namespace, String name, String id,
Consumer<EntityData> transform Consumer<EntityData> transform
) { ) {
EntityDataRegistry.getInstance().register(namespace, name, new Factory<EntityData>() { EntityDataRegistry.getInstance().register(id, new Factory<EntityData>() {
@Override @Override
public EntityData build() { public EntityData build() {
EntityData entity = new EntityData(namespace, name); EntityData entity = new EntityData(id);
transform.accept(entity); transform.accept(entity);
return entity; return entity;
} }

View File

@ -7,10 +7,14 @@ import ru.windcorp.progressia.common.world.entity.EntityData;
public class TestEntityDataStatie extends EntityData { public class TestEntityDataStatie extends EntityData {
private final IntStateField size = private final IntStateField size =
field("Test", "Size").setShared().ofInt().build(); field("Test:Size").setShared().ofInt().build();
public TestEntityDataStatie() { public TestEntityDataStatie() {
super("Test", "Statie"); this("Test:Statie");
}
protected TestEntityDataStatie(String id) {
super(id);
setCollisionModel(new AABB(0, 0, 0, 1, 1, 1)); setCollisionModel(new AABB(0, 0, 0, 1, 1, 1));
setSizeNow(16); setSizeNow(16);
} }

View File

@ -7,8 +7,8 @@ import ru.windcorp.progressia.server.world.entity.EntityLogic;
public class TestEntityLogicStatie extends EntityLogic { public class TestEntityLogicStatie extends EntityLogic {
public TestEntityLogicStatie() { public TestEntityLogicStatie(String id) {
super("Test", "Statie"); super(id);
} }
@Override @Override

View File

@ -9,6 +9,7 @@ import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.client.graphics.model.Shapes.PppBuilder; import ru.windcorp.progressia.client.graphics.model.Shapes.PppBuilder;
import ru.windcorp.progressia.client.graphics.model.StaticModel; import ru.windcorp.progressia.client.graphics.model.StaticModel;
import ru.windcorp.progressia.client.graphics.texture.ComplexTexture; import ru.windcorp.progressia.client.graphics.texture.ComplexTexture;
import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive;
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
import ru.windcorp.progressia.client.world.entity.HumanoidModel; import ru.windcorp.progressia.client.world.entity.HumanoidModel;
import ru.windcorp.progressia.client.world.entity.EntityRender; import ru.windcorp.progressia.client.world.entity.EntityRender;
@ -30,11 +31,15 @@ public class TestEntityRenderHuman extends EntityRender {
private final Renderable leftLeg; private final Renderable leftLeg;
private final Renderable rightLeg; private final Renderable rightLeg;
public TestEntityRenderHuman() { private final TexturePrimitive skin;
super("Test", "Player");
public TestEntityRenderHuman(String id) {
super(id);
this.skin = fetchSkin();
ComplexTexture texture = new ComplexTexture( ComplexTexture texture = new ComplexTexture(
EntityRenderRegistry.getEntityTexture("pyotr"), this.skin,
16, 16 16, 16
); );
@ -47,6 +52,14 @@ public class TestEntityRenderHuman extends EntityRender {
this.rightLeg = createLimb(texture, 0, 8, 0, 4, false, false); this.rightLeg = createLimb(texture, 0, 8, 0, 4, false, false);
} }
protected TexturePrimitive fetchSkin() {
return EntityRenderRegistry.getEntityTexture("pyotr");
}
public TexturePrimitive getSkin() {
return skin;
}
private Renderable createBody(ComplexTexture texture) { private Renderable createBody(ComplexTexture texture) {
return createLayeredCuboid( return createLayeredCuboid(
texture, texture,

View File

@ -32,8 +32,8 @@ public class TestEntityRenderJavapony extends EntityRender {
private final Renderable rightForeLeg; private final Renderable rightForeLeg;
private final Renderable rightHindLeg; private final Renderable rightHindLeg;
public TestEntityRenderJavapony() { public TestEntityRenderJavapony(String id) {
super("Test", "Javapony"); super(id);
ComplexTexture texture = new ComplexTexture( ComplexTexture texture = new ComplexTexture(
EntityRenderRegistry.getEntityTexture("javapony"), EntityRenderRegistry.getEntityTexture("javapony"),

View File

@ -19,8 +19,8 @@ public class TestEntityRenderStatie extends EntityRender {
.setColorMultiplier(1, 1, 0) .setColorMultiplier(1, 1, 0)
.create(); .create();
public TestEntityRenderStatie() { public TestEntityRenderStatie(String id) {
super("Test", "Statie"); super(id);
} }
@Override @Override

View File

@ -0,0 +1,70 @@
package ru.windcorp.jputil.chars.stringUtil;
import static org.junit.Assert.assertArrayEquals;
import java.util.Random;
import org.junit.Test;
import ru.windcorp.jputil.chars.StringUtil;
public class SplitAtTest {
@Test
public void testExamplesFromDocs() {
test("a.b.c", new int[] {1, 3}, new String[] {"a", "b", "c"});
test("a..b", new int[] {1, 2}, new String[] {"a", "", "b"});
test(".b.", new int[] {0, 2}, new String[] {"", "b", ""});
test("a.b", new int[] {1, 1, 1}, new String[] {"a", "", "", "b"});
}
@Test
public void testIndexPermutations() {
Random random = new Random(0);
int stringLength = 1000;
char[] chars = new char[stringLength];
for (int i = 0; i < stringLength; ++i) {
chars[i] = (char) ('a' + random.nextInt('z' - 'a'));
}
String src = new String(chars);
int[] indices = new int[100];
for (int i = 0; i < indices.length; ++i) {
indices[i] = random.nextInt(stringLength);
}
String[] expected = StringUtil.splitAt(src, indices);
for (int i = 0; i < 10000; ++i) {
shuffleArray(indices, random);
int[] copy = indices.clone();
test(src, indices, expected);
assertArrayEquals(indices, copy); // Make sure indices array hasn't changed
}
}
// Shamelessly copied from
// https://stackoverflow.com/a/1520212/4463352
// Thanks, https://stackoverflow.com/users/15459/philho!
// Implementing FisherYates shuffle
private static void shuffleArray(int[] ar, Random random) {
for (int i = ar.length - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
private void test(String string, int[] at, String[] expecteds) {
assertArrayEquals(expecteds, StringUtil.splitAt(string, at));
}
}

View File

@ -29,38 +29,40 @@ import java.util.Random;
import org.junit.Test; import org.junit.Test;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.namespaces.IllegalIdException;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil;
public class NamespacedTest { public class NamespacedTest {
class TestNamespaced extends Namespaced { class TestNamespaced extends Namespaced {
public TestNamespaced(String namespace, String name) { public TestNamespaced(String id) {
super(namespace, name); super(id);
} }
} }
void shouldReject(String a, String b) { void shouldReject(String a, String b) {
try { try {
new TestNamespaced(a, b); new TestNamespaced(NamespacedUtil.getId(a, b));
} catch (IllegalArgumentException | NullPointerException e) { } catch (IllegalIdException | NullPointerException e) {
try { try {
new TestNamespaced(b, a); new TestNamespaced(NamespacedUtil.getId(b, a));
} catch (IllegalArgumentException | NullPointerException e1) { } catch (IllegalIdException | NullPointerException e1) {
return; return;
} }
} }
throw new AssertionFailedError("Expected NPE or IAE for: \"" + a + "\":\"" + b + "\""); throw new AssertionFailedError("Expected NPE or IllegalIdException for: \"" + a + "\":\"" + b + "\"");
} }
@Test @Test
public void shouldAllow() { public void shouldAllow() {
new TestNamespaced("Something", "Usual"); new TestNamespaced("Something:Usual");
new TestNamespaced("Vry", "Sml"); new TestNamespaced("Vry:Sml");
new TestNamespaced("ALL", "CAPS"); new TestNamespaced("ALL:CAPS");
new TestNamespaced("WithDigits12345", "MoreDigits67890"); new TestNamespaced("WithDigits12345:MoreDigits67890");
} }
@Test @Test
@ -80,17 +82,17 @@ public class NamespacedTest {
shouldReject("XS", "Normal"); shouldReject("XS", "Normal");
shouldReject("", "Normal"); shouldReject("", "Normal");
shouldReject("Contains:separators", "Normal"); shouldReject("Contains:separators", "Normal");
shouldReject("СодержитРусский", "Normal"); shouldReject("СодержитНеАльфанум", "Normal");
} }
@Test @Test
public void shouldRejectGarbage() { public void shouldRejectGarbage() {
Random random = new Random(0); Random random = new Random(0);
byte[] bytes = new byte[1024]; byte[] bytes = new byte[NamespacedUtil.MAX_NAME_LENGTH];
for (int attempt = 0; attempt < 10000; ++attempt) { for (int attempt = 0; attempt < 10000; ++attempt) {
random.nextBytes(bytes); random.nextBytes(bytes);
bytes[0] = 'a'; // Make sure it is invalid bytes[bytes.length - 1] = '!'; // Make sure it is invalid
shouldReject(new String(bytes), "ContainsUtterGarbage"); shouldReject(new String(bytes), "ContainsUtterGarbage");
} }
} }
@ -108,8 +110,8 @@ public class NamespacedTest {
String namespace = getRandomValidString(random); String namespace = getRandomValidString(random);
String name = getRandomValidString(random); String name = getRandomValidString(random);
TestNamespaced a = new TestNamespaced(namespace, name); TestNamespaced a = new TestNamespaced(NamespacedUtil.getId(namespace, name));
TestNamespaced b = new TestNamespaced(namespace, name); TestNamespaced b = new TestNamespaced(NamespacedUtil.getId(namespace, name));
contains.add(a); contains.add(a);
hashSet.add(b); hashSet.add(b);
@ -119,7 +121,7 @@ public class NamespacedTest {
String namespace = getRandomValidString(random); String namespace = getRandomValidString(random);
String name = getRandomValidString(random); String name = getRandomValidString(random);
TestNamespaced c = new TestNamespaced(namespace, name); TestNamespaced c = new TestNamespaced(NamespacedUtil.getId(namespace, name));
doesNotContain.add(c); doesNotContain.add(c);
} }
@ -128,7 +130,7 @@ public class NamespacedTest {
Iterator<TestNamespaced> it = doesNotContain.iterator(); Iterator<TestNamespaced> it = doesNotContain.iterator();
while (it.hasNext()) { while (it.hasNext()) {
TestNamespaced next = it.next(); TestNamespaced next = it.next();
if (next.getName().equals(x.getName()) && next.getNamespace().equals(x.getNamespace())) { if (next.getId().equals(x.getId())) {
it.remove(); it.remove();
} }
} }
@ -144,7 +146,7 @@ public class NamespacedTest {
} }
String getRandomValidString(Random random) { String getRandomValidString(Random random) {
char[] chars = new char[random.nextInt(100) + 3]; char[] chars = new char[random.nextInt(NamespacedUtil.MAX_NAME_LENGTH - 3) + 3];
for (int i = 0; i < chars.length; ++i) { for (int i = 0; i < chars.length; ++i) {
switch (random.nextInt(3)) { switch (random.nextInt(3)) {