New: Indirect Ionization (tm)

master
Ondřej Hruška 10 years ago
parent a5bcb22ef2
commit d7d4d181a1
  1. 2
      .project
  2. 29
      src/mightypork/utils/Profiler.java
  3. 47
      src/mightypork/utils/Reflect.java
  4. 17
      src/mightypork/utils/eventbus/EventBus.java
  5. 235
      src/mightypork/utils/ion/Ion.java
  6. 2
      src/mightypork/utils/ion/IonBinary.java
  7. 26
      src/mightypork/utils/ion/IonBundled.java
  8. 30
      src/mightypork/utils/ion/IonDataBundle.java
  9. 61
      src/mightypork/utils/ion/IonInput.java
  10. 2
      src/mightypork/utils/ion/IonMapWrapper.java
  11. 16
      src/mightypork/utils/ion/IonObjBundled.java
  12. 37
      src/mightypork/utils/ion/IonOutput.java
  13. 2
      src/mightypork/utils/ion/IonSequenceWrapper.java
  14. 38
      src/mightypork/utils/ion/IonizerBinary.java
  15. 35
      src/mightypork/utils/ion/IonizerBundled.java
  16. 19
      src/mightypork/utils/math/algo/Move.java

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>mighty_utils</name>
<name>MightyUtils</name>
<comment></comment>
<projects>
</projects>

@ -0,0 +1,29 @@
package mightypork.utils;
public class Profiler {
public static long begin()
{
return System.currentTimeMillis();
}
public static double end(long begun)
{
return endLong(begun) / 1000D;
}
public static long endLong(long begun)
{
return System.currentTimeMillis() - begun;
}
public static String endStr(long begun)
{
return Support.str(end(begun)) + " s";
}
}

@ -2,6 +2,10 @@ package mightypork.utils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
@ -36,4 +40,47 @@ public class Reflect {
return tested.getClass().isAnnotationPresent(annotation);
}
/**
* Get generic parameters of a class
*
* @param clazz the examined class
* @return parameter types
*/
public static Class<?>[] getGenericParameters(Class<?> clazz)
{
// BEHOLD, MAGIC!
final Type evtc = clazz.getGenericSuperclass();
if (evtc instanceof ParameterizedType) {
final Type[] types = ((ParameterizedType) evtc).getActualTypeArguments();
final Class<?>[] classes = new Class<?>[types.length];
for (int i = 0; i < types.length; i++) {
classes[i] = (Class<?>) types[i];
}
return classes;
}
throw new RuntimeException(Support.str(clazz) + " is not generic.");
}
public static Object getConstantFieldValue(Class<?> objClass, String fieldName) throws ReflectiveOperationException
{
final Field fld = objClass.getDeclaredField(fieldName);
final int modif = fld.getModifiers();
if (!Modifier.isFinal(modif) || !Modifier.isStatic(modif)) {
throw new RuntimeException("The " + fieldName + " field of " + Support.str(objClass) + " field must be static and final!");
}
fld.setAccessible(true);
return fld.get(null);
}
}

@ -1,8 +1,6 @@
package mightypork.utils.eventbus;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
@ -112,20 +110,7 @@ final public class EventBus implements Destroyable, BusAccess {
private static Class<?> getEventListenerClass(BusEvent<?> event)
{
// BEHOLD, MAGIC!
final Type evtc = event.getClass().getGenericSuperclass();
if (evtc instanceof ParameterizedType) {
if (((ParameterizedType) evtc).getRawType() == BusEvent.class) {
final Type[] types = ((ParameterizedType) evtc).getActualTypeArguments();
for (final Type genericType : types) {
return (Class<?>) genericType;
}
}
}
throw new RuntimeException("Could not detect event listener type.");
return Reflect.getGenericParameters(event.getClass())[0];
}
/** Log detailed messages (debug) */

@ -7,13 +7,13 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import mightypork.utils.Reflect;
import mightypork.utils.Support;
/**
@ -90,13 +90,16 @@ public class Ion {
private static Map<Integer, Class<?>> markToClass = new HashMap<>();
private static Map<Class<?>, Integer> classToMark = new HashMap<>();
private static Map<Class<?>, IonizerBinary<?>> ionizersBinary = new HashMap<>();
private static Map<Class<?>, IonizerBundled<?>> ionizersBundled = new HashMap<>();
private static boolean reservedMarkChecking;
static {
reservedMarkChecking = false;
// register built-ins
register(ION_BUNDLE, IonBundle.class);
register(ION_BUNDLE, IonDataBundle.class);
register(SEQUENCE_WRAPPER, IonSequenceWrapper.class);
register(MAP_WRAPPER, IonMapWrapper.class);
@ -105,70 +108,123 @@ public class Ion {
/**
* Register new {@link IonObjBinary} class for writing/loading.
* Register a type for writing/loading.
*
* @param mark mark to be used 50..255, unless internal
* @param mark binary ION mark
* @param objClass class of the registered object
*/
public static void register(int mark, Class<?> objClass)
{
// negative marks are allowed.
if (mark > RANGE_HIGH) throw new IllegalArgumentException("Mark must be < 256.");
if (mark < RANGE_LOW) throw new IllegalArgumentException("Mark must be positive.");
if (reservedMarkChecking && isMarkReserved(mark)) {
throw new IllegalArgumentException("Marks " + RESERVED_LOW + ".." + RESERVED_HIGH + " are reserved.");
}
if (markToClass.containsKey(objClass)) {
throw new IllegalArgumentException("Mark " + mark + " is already in use.");
}
if (classToMark.containsKey(objClass)) {
throw new IllegalArgumentException(objClass + " is already registered.");
}
if (!IonObjBundled.class.isAssignableFrom(objClass)) {
if (!IonObjBinary.class.isAssignableFrom(objClass)) {
throw new IllegalArgumentException(objClass + " cannot be registered to Ion.");
if (!IonBinary.class.isAssignableFrom(objClass)) {
if (!IonBundled.class.isAssignableFrom(objClass)) {
throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass));
}
}
// make sure the type has implicit constructor
try {
objClass.getConstructor();
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException("Class " + objClass + " doesn't have an implicit constructor.");
}
assertHasImplicitConstructor(objClass);
markToClass.put(mark, objClass);
classToMark.put(objClass, mark);
registerUsingMark(mark, objClass);
}
/**
* Try to register the type using a static final ION_MARK int field.
* Try to register a type using a static final ION_MARK int field.
*
* @param objClass type class
*/
public static void register(Class<?> objClass)
{
try {
final Field fld = objClass.getDeclaredField("ION_MARK");
final int modif = fld.getModifiers();
if (!Modifier.isFinal(modif) || !Modifier.isStatic(modif)) {
throw new RuntimeException("The ION_MARK field must be static and final.");
if (!IonBinary.class.isAssignableFrom(objClass)) {
if (!IonBundled.class.isAssignableFrom(objClass)) {
throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass));
}
}
assertHasImplicitConstructor(objClass);
registerUsingConstant(objClass);
}
private static void registerUsingMark(int mark, Class<?> objClass)
{
assertMarkAvailable(mark, objClass);
markToClass.put(mark, objClass);
classToMark.put(objClass, mark);
}
public static void registerUsingConstant(Class<?> objClass)
{
try {
final int mark = ((Number) Reflect.getConstantFieldValue(objClass, "ION_MARK")).intValue();
fld.setAccessible(true);
final int mark = fld.getInt(null);
register(mark, objClass);
registerUsingMark(mark, objClass);
} catch (final Exception e) {
throw new RuntimeException("Could not register " + objClass + " using an ION_MARK field.", e);
throw new RuntimeException("Could not register " + Support.str(objClass) + " using an ION_MARK field.", e);
}
}
/**
* Register new binary ionizer.
*
* @param mark binary ION mark
* @param ionizer ionizer
*/
public static void registerIndirect(int mark, IonizerBinary<?> ionizer)
{
final Class<?> objClass = Reflect.getGenericParameters(ionizer.getClass())[0];
registerUsingMark(mark, objClass);
ionizersBinary.put(objClass, ionizer);
}
/**
* Register new bundled ionizer.
*
* @param mark binary ION mark
* @param ionizer ionizer
*/
public static void registerIndirect(int mark, IonizerBundled<?> ionizer)
{
final Class<?> objClass = Reflect.getGenericParameters(ionizer.getClass())[0];
registerUsingMark(mark, objClass);
ionizersBundled.put(objClass, ionizer);
}
private static void assertHasImplicitConstructor(Class<?> objClass)
{
try {
objClass.getConstructor();
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException("Class " + objClass + " doesn't have an implicit constructor.");
}
}
private static void assertMarkAvailable(int mark, Class<?> objClass)
{
// negative marks are allowed.
if (mark > RANGE_HIGH) throw new IllegalArgumentException("Mark must be < 256.");
if (mark < RANGE_LOW) throw new IllegalArgumentException("Mark must be positive.");
if (reservedMarkChecking && isMarkReserved(mark)) {
throw new IllegalArgumentException("Marks " + RESERVED_LOW + ".." + RESERVED_HIGH + " are reserved.");
}
if (markToClass.containsKey(mark)) {
throw new IllegalArgumentException("Mark " + mark + " is already in use.");
}
if (classToMark.containsKey(objClass)) {
throw new IllegalArgumentException(Support.str(objClass) + " is already registered.");
}
}
@ -297,9 +353,9 @@ public class Ion {
/**
* Create new bundle and write the object to it.
*/
public static IonBundle wrapBundled(IonObjBundled content) throws IOException
public static IonDataBundle wrapBundled(IonBundled content) throws IOException
{
final IonBundle ib = new IonBundle();
final IonDataBundle ib = new IonDataBundle();
content.save(ib);
return ib;
}
@ -314,14 +370,14 @@ public class Ion {
* @return the object unwrapped
* @throws IOException
*/
public static <T extends IonObjBundled> T unwrapBundled(IonBundle bundle, Class<? extends T> objClass) throws IOException
public static <T extends IonBundled> T unwrapBundled(IonDataBundle bundle, Class<? extends T> objClass) throws IOException
{
try {
final T inst = objClass.newInstance();
inst.load(bundle);
return inst;
} catch (InstantiationException | IllegalAccessException e) {
throw new IOException("Could not instantiate " + objClass + ".");
throw new IOException("Could not instantiate " + Support.str(objClass) + ".");
}
}
@ -332,6 +388,18 @@ public class Ion {
}
static IonizerBinary<?> getIonizerBinaryForClass(Class<?> clz)
{
return ionizersBinary.get(clz);
}
static IonizerBundled<?> getIonizerBundledForClass(Class<?> clz)
{
return ionizersBundled.get(clz);
}
public static int getMark(Object object)
{
assertRegistered(object);
@ -341,24 +409,48 @@ public class Ion {
/**
* @return true if the mark is for a registered {@link IonObjBinary} object
* @return true if the mark is for a registered {@link IonBinary} object
*/
static boolean isMarkForBinary(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return IonObjBinary.class.isAssignableFrom(markToClass.get(mark));
return IonBinary.class.isAssignableFrom(markToClass.get(mark));
}
/**
* @return true if the mark is for a registered {@link IonObjBinary} object
* @return true if the mark is for a registered {@link IonBinary} object
*/
static boolean isMarkForBundled(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return IonObjBundled.class.isAssignableFrom(markToClass.get(mark));
return IonBundled.class.isAssignableFrom(markToClass.get(mark));
}
/**
* @return true if the mark is for a registered indirectly saved binary
* object
*/
static boolean isMarkForIndirectBinary(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return ionizersBinary.containsKey(markToClass.get(mark));
}
/**
* @return true if the mark is for a registered indirectly saved bundled
* object
*/
static boolean isMarkForIndirectBundled(int mark)
{
if (!markToClass.containsKey(mark)) return false;
return ionizersBundled.containsKey(markToClass.get(mark));
}
@ -372,11 +464,14 @@ public class Ion {
/**
* @return true if the mark is for a registered {@link IonObjBinary} object
* @return true if the mark is for a registered {@link IonBinary} object
*/
static boolean isRegistered(Object object)
{
return classToMark.containsKey(object.getClass());
final Class<?> clazz = object.getClass();
if (classToMark.containsKey(clazz)) return true;
return false;
}
@ -388,7 +483,7 @@ public class Ion {
static void assertRegistered(Object obj)
{
if (!isRegistered(obj)) {
throw new RuntimeException("Type not registered: " + (obj.getClass()));
throw new RuntimeException("Type not registered: " + Support.str(obj.getClass()));
}
}
@ -400,16 +495,34 @@ public class Ion {
public static void reset()
{
final List<Integer> toRemove = new ArrayList<>();
for (final Entry<Integer, Class<?>> e : markToClass.entrySet()) {
final int mark = e.getKey();
// remove direct
for (final Integer mark : markToClass.keySet()) {
if (!isMarkReserved(mark)) {
toRemove.add(mark);
}
}
for (final int i : toRemove) {
classToMark.remove(markToClass.remove(i));
final Class<?> clz = markToClass.remove(i);
classToMark.remove(clz);
ionizersBinary.remove(clz);
ionizersBundled.remove(clz);
}
}
public static boolean isObjectIndirectBundled(Object obj)
{
return ionizersBundled.containsKey(obj.getClass());
}
public static boolean isObjectIndirectBinary(Object obj)
{
return ionizersBinary.containsKey(obj.getClass());
}
}

@ -10,7 +10,7 @@ import java.io.IOException;
*
* @author Ondřej Hruška (MightyPork)
*/
public interface IonObjBinary {
public interface IonBinary {
/**
* Load data from the input stream.

@ -0,0 +1,26 @@
package mightypork.utils.ion;
/**
* Bundled ion object. If a class implements both binary and bundled, then
* binary will be preferred by both IonInput and IonOutput.
*
* @author Ondřej Hruška (MightyPork)
*/
public interface IonBundled {
/**
* Load this object from the data bundle
*
* @param in bundle to load from
*/
void load(IonDataBundle in);
/**
* Save this object to the data bundle
*
* @param out bundle to save into
*/
void save(IonDataBundle out);
}

@ -15,7 +15,7 @@ import java.util.Map;
*
* @author Ondřej Hruška (MightyPork)
*/
public class IonBundle implements IonObjBinary {
public class IonDataBundle implements IonBinary {
private final Map<String, Object> backingMap = new HashMap<>();
@ -26,11 +26,11 @@ public class IonBundle implements IonObjBinary {
* @param key key
* @param filled bundle to fill
*/
public void loadBundle(String key, IonBundle filled)
public void loadBundle(String key, IonDataBundle filled)
{
if (!containsKey(key)) return;
final IonBundle ib = get(key, new IonBundle());
final IonDataBundle ib = get(key, new IonDataBundle());
filled.clear();
filled.putAll(ib);
@ -127,9 +127,9 @@ public class IonBundle implements IonObjBinary {
* @param loaded loaded object
* @return the loaded object
*/
public <T extends IonObjBundled> T loadBundled(String key, T loaded)
public <T extends IonBundled> T loadBundled(String key, T loaded)
{
final IonBundle bu = get(key, null);
final IonDataBundle bu = get(key, null);
if (bu == null) throw new RuntimeException("No such key: " + key);
loaded.load(bu);
@ -145,9 +145,9 @@ public class IonBundle implements IonObjBinary {
* @param key key
* @param saved saved object
*/
public void putBundled(String key, IonObjBundled saved)
public void putBundled(String key, IonBundled saved)
{
final IonBundle bu = new IonBundle();
final IonDataBundle bu = new IonDataBundle();
saved.save(bu);
put(key, bu);
}
@ -184,15 +184,7 @@ public class IonBundle implements IonObjBinary {
}
public void put(String key, IonObjBundled value)
{
if (key == null || value == null) return;
if (!Ion.isRegistered(value)) throw new IllegalArgumentException("Cannot add to bundle, not registered: " + value);
backingMap.put(key, value);
}
public void put(String key, IonObjBinary value)
public void put(String key, Object value)
{
if (key == null || value == null) return;
if (!Ion.isRegistered(value)) throw new IllegalArgumentException("Cannot add to bundle, not registered: " + value);
@ -396,7 +388,7 @@ public class IonBundle implements IonObjBinary {
*
* @param anotherBundle another bundle
*/
public void putAll(IonBundle anotherBundle)
public void putAll(IonDataBundle anotherBundle)
{
backingMap.putAll(anotherBundle.backingMap);
}
@ -424,8 +416,8 @@ public class IonBundle implements IonObjBinary {
{
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof IonBundle)) return false;
final IonBundle other = (IonBundle) obj;
if (!(obj instanceof IonDataBundle)) return false;
final IonDataBundle other = (IonDataBundle) obj;
if (backingMap == null) {
if (other.backingMap != null) return false;
} else if (!backingMap.equals(other.backingMap)) return false;

@ -235,9 +235,9 @@ public class IonInput implements Closeable {
/**
* Read bundle without a mark
*/
public IonBundle readBundle() throws IOException
public IonDataBundle readBundle() throws IOException
{
final IonBundle ib = new IonBundle();
final IonDataBundle ib = new IonDataBundle();
ib.load(this);
return ib;
}
@ -246,7 +246,7 @@ public class IonInput implements Closeable {
/**
* Read bundle without a mark, load into a provided one
*/
public void readBundle(IonBundle filled) throws IOException
public void readBundle(IonDataBundle filled) throws IOException
{
filled.clear();
filled.load(this);
@ -276,16 +276,16 @@ public class IonInput implements Closeable {
*
* @param def default value.
* @return the loaded object
* @throws IOException
* @throws CorruptDataException
*/
@SuppressWarnings("unchecked")
public <T> T readObject(T def) throws IOException
public <T> T readObject(T def) throws CorruptDataException
{
try {
final Object o = readObject();
return (T) (o == null ? def : o);
} catch (final Exception e) {
throw new IOException("Could not load object.", e);
throw new CorruptDataException("Could not load object.", e);
}
}
@ -299,31 +299,42 @@ public class IonInput implements Closeable {
public Object readObject() throws IOException
{
final int mark = readMark();
if (Ion.isMarkForBinary(mark)) {
IonObjBinary loaded;
try {
try {
loaded = (IonObjBinary) Ion.getClassForMark(mark).newInstance();
} catch (final Exception e) {
throw new RuntimeException("Could not load binary object with mark: " + mark, e);
if (Ion.isMarkForBinary(mark)) {
IonBinary loaded;
loaded = (IonBinary) Ion.getClassForMark(mark).newInstance();
loaded.load(this);
return loaded;
}
loaded.load(this);
return loaded;
}
if (Ion.isMarkForBundled(mark)) {
IonObjBundled loaded;
if (Ion.isMarkForBundled(mark)) {
IonBundled loaded;
loaded = (IonBundled) Ion.getClassForMark(mark).newInstance();
final IonDataBundle ib = readBundle();
loaded.load(ib);
return loaded;
}
try {
loaded = (IonObjBundled) Ion.getClassForMark(mark).newInstance();
} catch (final Exception e) {
throw new RuntimeException("Could not load bundled object with mark: " + mark, e);
if (Ion.isMarkForIndirectBundled(mark)) {
final IonizerBundled<?> ionizer = Ion.getIonizerBundledForClass(Ion.getClassForMark(mark));
return ionizer.load(readBundle());
}
final IonBundle ib = readBundle();
loaded.load(ib);
return loaded;
if (Ion.isMarkForIndirectBinary(mark)) {
final IonizerBinary<?> ionizer = Ion.getIonizerBinaryForClass(Ion.getClassForMark(mark));
return ionizer.load(this);
}
} catch (final Exception e) {
throw new RuntimeException("Could not load object for mark: " + mark, e);
}
switch (mark) {

@ -7,7 +7,7 @@ import java.util.Map;
@SuppressWarnings({ "rawtypes", "unchecked" })
class IonMapWrapper implements IonObjBinary {
class IonMapWrapper implements IonBinary {
private final Map map;

@ -1,16 +0,0 @@
package mightypork.utils.ion;
/**
* Bundled ion object. If a class implements both binary and bundled, then
* binary will be preferred by both IonInput and IonOutput.
*
* @author Ondřej Hruška (MightyPork)
*/
public interface IonObjBundled {
void load(IonBundle in);
void save(IonBundle out);
}

@ -195,7 +195,7 @@ public class IonOutput implements Closeable {
/**
* Write a bundle without a mark
*/
public void writeBundle(IonBundle bundle) throws IOException
public void writeBundle(IonDataBundle bundle) throws IOException
{
bundle.save(this);
}
@ -279,26 +279,47 @@ public class IonOutput implements Closeable {
return;
}
if (obj instanceof IonObjBinary) {
final IonObjBinary iObj = (IonObjBinary) obj;
if (obj instanceof IonBinary) {
final IonBinary iObj = (IonBinary) obj;
writeMark(Ion.getMark(iObj));
writeMark(Ion.getMark(obj));
iObj.save(this);
return;
}
if (obj instanceof IonObjBundled) {
final IonObjBundled iObj = (IonObjBundled) obj;
if (obj instanceof IonBundled) {
final IonBundled iObj = (IonBundled) obj;
writeMark(Ion.getMark(iObj));
writeMark(Ion.getMark(obj));
final IonBundle bundle = new IonBundle();
final IonDataBundle bundle = new IonDataBundle();
iObj.save(bundle);
writeBundle(bundle);
return;
}
if (Ion.isObjectIndirectBundled(obj)) {
final IonizerBundled<?> ionizer = Ion.getIonizerBundledForClass(obj.getClass());
writeMark(Ion.getMark(obj));
final IonDataBundle bundle = new IonDataBundle();
ionizer._save(obj, bundle);
writeBundle(bundle);
return;
}
if (Ion.isObjectIndirectBinary(obj)) {
final IonizerBinary<?> ionizer = Ion.getIonizerBinaryForClass(obj.getClass());
writeMark(Ion.getMark(obj));
ionizer._save(obj, this);
return;
}
if (obj instanceof Map) {
writeMark(Ion.MAP);
writeMap((Map<?, ?>) obj);

@ -7,7 +7,7 @@ import java.util.Collection;
@SuppressWarnings({ "rawtypes", "unchecked" })
class IonSequenceWrapper implements IonObjBinary {
class IonSequenceWrapper implements IonBinary {
private Collection collection = new ArrayList();

@ -0,0 +1,38 @@
package mightypork.utils.ion;
import java.io.IOException;
/**
* External ionizer using a IonOutput / IonInput - can be used if the data type
* cannot be modified to implement the proper interface
*
* @author Ondřej Hruška (MightyPork)
* @param <T>
*/
public abstract class IonizerBinary<T> {
@SuppressWarnings("unchecked")
final void _save(Object object, IonOutput out) throws IOException{
save((T)object, out);
}
/**
* Save an object to ion output
*
* @param object object to save
* @param out ion output
* @throws IOException
*/
public abstract void save(T object, IonOutput out) throws IOException;
/**
* Load an object from ion input
*
* @param in ion input
* @return the loaded object
*/
public abstract T load(IonInput in) throws IOException;
}

@ -0,0 +1,35 @@
package mightypork.utils.ion;
/**
* External ionizer using a data bundle - can be used if the data type cannot be
* modified to implement the proper interface
*
* @author Ondřej Hruška (MightyPork)
* @param <T>
*/
public abstract class IonizerBundled<T> {
@SuppressWarnings("unchecked")
final void _save(Object object, IonDataBundle out) {
save((T)object, out);
}
/**
* Save an object to data bundle
*
* @param object object to save
* @param out bundle to save to
*/
public abstract void save(T object, IonDataBundle out);
/**
* Load an object from a bundle
*
* @param in bundle to load from
* @return the loaded object
*/
public abstract T load(IonDataBundle in);
}

@ -30,15 +30,9 @@ public class Move {
return new Move(x, y);
}
private byte x;
private byte y;
public Move()
{
// for ion
}
private final byte x;
private final byte y;
public Move(int x, int y)
{
@ -70,11 +64,4 @@ public class Move {
{
return "(" + x + " ; " + y + ")";
}
protected void setTo(byte x, byte y)
{
this.x = x;
this.y = y;
}
}

Loading…
Cancel
Save