fix: Refactored to Gradle-based project, and added dependencies
This commit is contained in:
@ -0,0 +1,247 @@
|
||||
package uulm.teamname.marvelous.gamelibrary;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Represents a 2d vector of integers.
|
||||
*/
|
||||
public class IntVector2 implements Serializable {
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
public final static IntVector2 X = new IntVector2(1, 0);
|
||||
public final static IntVector2 Y = new IntVector2(0, 1);
|
||||
public final static IntVector2 Zero = new IntVector2(0, 0);
|
||||
|
||||
private final static float nearZero = 0.000000001f;
|
||||
|
||||
public IntVector2(int x, int y) {
|
||||
set(x, y);
|
||||
}
|
||||
|
||||
public IntVector2(IntVector2 v) {
|
||||
set(v);
|
||||
}
|
||||
|
||||
public IntVector2 copy() {
|
||||
return new IntVector2(this);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public static float length(int x, int y) {
|
||||
return (float)Math.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public float length() {
|
||||
return IntVector2.length(this.x, this.y);
|
||||
}
|
||||
|
||||
public static float length2(int x, int y) {
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
public float length2 () {
|
||||
return IntVector2.length2(this.x, this.y);
|
||||
}
|
||||
|
||||
public IntVector2 set(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntVector2 set(IntVector2 v) {
|
||||
return set(v.x, v.y);
|
||||
}
|
||||
|
||||
public IntVector2 sub(int x, int y) {
|
||||
this.x -= x;
|
||||
this.y -= y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntVector2 sub(IntVector2 v) {
|
||||
return sub(v.x, v.y);
|
||||
}
|
||||
|
||||
public IntVector2 add(int x, int y) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntVector2 add(IntVector2 v) {
|
||||
return add(v.x, v.y);
|
||||
}
|
||||
|
||||
public static float dot(float x1, float y1, float x2, float y2) {
|
||||
return x1 * x2 + y1 * y2;
|
||||
}
|
||||
|
||||
public float dot(float ox, float oy) {
|
||||
return IntVector2.dot(this.x, this.y, ox, oy);
|
||||
}
|
||||
|
||||
public float dot(IntVector2 v) {
|
||||
return dot(v.x, v.y);
|
||||
}
|
||||
|
||||
public IntVector2 scale(float x, float y) {
|
||||
this.x *= x;
|
||||
this.y *= y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntVector2 scale(float scalar) {
|
||||
return scale(scalar, scalar);
|
||||
}
|
||||
|
||||
public IntVector2 scale(IntVector2 v) {
|
||||
return scale(v.x, v.y);
|
||||
}
|
||||
|
||||
public static float distance(int x1, int y1, int x2, int y2) {
|
||||
final float x_d = x2 - x1;
|
||||
final float y_d = y2 - y1;
|
||||
return (float)Math.sqrt(x_d * x_d + y_d * y_d);
|
||||
}
|
||||
|
||||
public float distance(int x, int y) {
|
||||
return IntVector2.distance(this.x, this.y, x, y);
|
||||
}
|
||||
|
||||
public float distance(IntVector2 v) {
|
||||
return distance(v.x, v.y);
|
||||
}
|
||||
|
||||
public static float distance2(int x1, int y1, int x2, int y2) {
|
||||
final float x_d = x2 - x1;
|
||||
final float y_d = y2 - y1;
|
||||
return x_d * x_d + y_d * y_d;
|
||||
}
|
||||
|
||||
public float distance2(int x, int y) {
|
||||
return IntVector2.distance2(this.x, this.y, x, y);
|
||||
}
|
||||
|
||||
public float distance2(IntVector2 v) {
|
||||
return distance2(v.x, v.y);
|
||||
}
|
||||
|
||||
public IntVector2 setLength(float len) {
|
||||
return setLength2(len * len);
|
||||
}
|
||||
|
||||
public IntVector2 setLength2(float len2) {
|
||||
float oldLen2 = length2();
|
||||
return (oldLen2 == 0 || oldLen2 == len2) ? this : scale((float)Math.sqrt(len2 / oldLen2));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "(" + x + "," + y + ")";
|
||||
}
|
||||
|
||||
public IntVector2 fromString(String v) throws NumberFormatException {
|
||||
int s = v.indexOf(',', 1);
|
||||
if (s != -1 && v.charAt(0) == '(' && v.charAt(v.length() - 1) == ')') {
|
||||
try {
|
||||
int x = Integer.parseInt(v.substring(1, s));
|
||||
int y = Integer.parseInt(v.substring(s + 1, v.length() - 1));
|
||||
return this.set(x, y);
|
||||
}catch (NumberFormatException ex) {
|
||||
//ok
|
||||
}
|
||||
}
|
||||
throw new NumberFormatException("Malformed IntVector2: " + v);
|
||||
}
|
||||
|
||||
public float cross(float x, float y) {
|
||||
return this.x * y - this.y * x;
|
||||
}
|
||||
|
||||
public float cross(IntVector2 v) {
|
||||
return cross(v.x, v.y);
|
||||
}
|
||||
|
||||
public boolean isUnit(final float margin) {
|
||||
return Math.abs(length2() - 1f) < margin;
|
||||
}
|
||||
|
||||
public boolean isUnit() {
|
||||
return isUnit(nearZero);
|
||||
}
|
||||
|
||||
public boolean isZero() {
|
||||
return x == 0 && y == 0;
|
||||
}
|
||||
|
||||
public boolean isZero(final float margin) {
|
||||
return length2() < margin;
|
||||
}
|
||||
|
||||
public boolean isOnLine(IntVector2 other, float epsilon) {
|
||||
return Math.abs(x * other.y - y * other.x) <= epsilon;
|
||||
}
|
||||
|
||||
public boolean isOnLine(IntVector2 other) {
|
||||
return isOnLine(other, nearZero);
|
||||
}
|
||||
|
||||
public boolean isCollinear(IntVector2 other, float epsilon) {
|
||||
return isOnLine(other, epsilon) && dot(other) > 0f;
|
||||
}
|
||||
|
||||
public boolean isCollinear(IntVector2 other) {
|
||||
return isOnLine(other) && dot(other) > 0f;
|
||||
}
|
||||
|
||||
public boolean isCollinearOpposite(IntVector2 other, float epsilon) {
|
||||
return isOnLine(other, epsilon) && dot(other) < 0f;
|
||||
}
|
||||
|
||||
public boolean isCollinearOpposite(IntVector2 other) {
|
||||
return isOnLine(other) && dot(other) < 0f;
|
||||
}
|
||||
|
||||
public boolean isPerpendicular(IntVector2 vector) {
|
||||
return isPerpendicular(vector,nearZero);
|
||||
}
|
||||
|
||||
public boolean isPerpendicular(IntVector2 vector, float epsilon) {
|
||||
return Math.abs(dot(vector)) <= epsilon;
|
||||
}
|
||||
|
||||
public boolean hasSameDirection(IntVector2 vector) {
|
||||
return dot(vector) > 0;
|
||||
}
|
||||
|
||||
public boolean hasOppositeDirection(IntVector2 vector) {
|
||||
return dot(vector) < 0;
|
||||
}
|
||||
|
||||
public IntVector2 setZero() {
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(this == o) return true;
|
||||
if(o == null || getClass() != o.getClass()) return false;
|
||||
IntVector2 that = (IntVector2) o;
|
||||
return x == that.x && y == that.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y);
|
||||
}
|
||||
}
|
15
src/main/java/uulm/teamname/marvelous/gamelibrary/Tuple.java
Normal file
15
src/main/java/uulm/teamname/marvelous/gamelibrary/Tuple.java
Normal file
@ -0,0 +1,15 @@
|
||||
package uulm.teamname.marvelous.gamelibrary;
|
||||
|
||||
/** Represents a pair of two objects.
|
||||
*/
|
||||
public class Tuple<X, Y> {
|
||||
public final X item1;
|
||||
public final Y item2;
|
||||
|
||||
/** Constructs a new {@link Tuple} based on the given objects.
|
||||
*/
|
||||
public Tuple(X item1, Y item2) {
|
||||
this.item1 = item1;
|
||||
this.item2 = item2;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
|
||||
/** Represents a playable character inside a match.
|
||||
*/
|
||||
public class Character extends Entity {
|
||||
/** The name of the character.
|
||||
*/
|
||||
public final String name;
|
||||
|
||||
/** The hp stat of the character.
|
||||
*/
|
||||
public final Stat hp;
|
||||
|
||||
/** The mp stat of the character.
|
||||
*/
|
||||
public final Stat mp;
|
||||
|
||||
/** The ap stat of the character.
|
||||
*/
|
||||
public final Stat ap;
|
||||
|
||||
/** The ranged attack range of the character.
|
||||
*/
|
||||
public final int attackRange;
|
||||
|
||||
/** The ranged attack damage of the character.
|
||||
*/
|
||||
public final int rangedDamage;
|
||||
|
||||
/** The melee attack damage of the character.
|
||||
*/
|
||||
public final int meleeDamage;
|
||||
|
||||
/** The {@link Inventory} of the character.
|
||||
*/
|
||||
public final Inventory inventory = new Inventory();
|
||||
|
||||
/** Constructs a new {@link Character} with an empty inventory.
|
||||
* @param id The {@link EntityID} of the character.
|
||||
* @param position The position of the character.
|
||||
* @param name The name of the character.
|
||||
* @param hp The maximum hp of the character.
|
||||
* @param mp The maximum mp of the character.
|
||||
* @param ap The maximum ap of the character.
|
||||
* @param attackRange The ranged attack range of the character.
|
||||
* @param rangedDamage The ranged damage of the character.
|
||||
* @param meleeDamage The melee damage of the character.
|
||||
*/
|
||||
public Character(EntityID id, IntVector2 position, String name, int hp, int mp, int ap, int attackRange, int rangedDamage, int meleeDamage) {
|
||||
super(id, position);
|
||||
this.name = name;
|
||||
this.hp = new Stat(StatType.HP, hp);
|
||||
this.mp = new Stat(StatType.MP, mp);
|
||||
this.ap = new Stat(StatType.AP, ap);
|
||||
this.attackRange = attackRange;
|
||||
this.rangedDamage = rangedDamage;
|
||||
this.meleeDamage = meleeDamage;
|
||||
}
|
||||
|
||||
/** Checks if the character is still alive.
|
||||
* @return Whether or not the characters hp is greater than 0.
|
||||
*/
|
||||
public boolean isAlive() {
|
||||
return hp.getValue() > 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
|
||||
/** Represents an abstract entity.
|
||||
*/
|
||||
public abstract class Entity {
|
||||
/** Whether or not the entity is currently active in the game.
|
||||
*/
|
||||
private boolean active = true;
|
||||
|
||||
/** The position of the entity.
|
||||
*/
|
||||
private IntVector2 position;
|
||||
|
||||
/** The {@link EntityID} of the entity.
|
||||
*/
|
||||
public final EntityID id;
|
||||
|
||||
/** Constructs a new {@link Entity}.
|
||||
* @param id The {@link EntityID} of the entity.
|
||||
* @param position The position of the entity.
|
||||
*/
|
||||
protected Entity(EntityID id, IntVector2 position) {
|
||||
this.position = position;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public IntVector2 getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(IntVector2 position) {
|
||||
this.position = position;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
/** Represents a distinct identification for every {@link Entity} in a game.
|
||||
*/
|
||||
public class EntityID {
|
||||
/** The index of the entity.
|
||||
*/
|
||||
public final int id;
|
||||
|
||||
/** The type of the entity.
|
||||
*/
|
||||
public final EntityType type;
|
||||
|
||||
/** Constructs a new {@link Entity}-{@link EntityID} based on the given index and {@link EntityType}.
|
||||
* @param id The index of the entity.
|
||||
* @param type The type of the entity.
|
||||
*/
|
||||
public EntityID(int id, EntityType type) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/** Checks if the id has the same {@link EntityType} as the given one.
|
||||
* @param other The type to compare to.
|
||||
* @return Whether or not the id has the same type.
|
||||
*/
|
||||
public boolean isSameType(EntityType other) {
|
||||
return type == other;
|
||||
}
|
||||
|
||||
/** Serializes the id for debugging.
|
||||
* @return A debug string containing all the necessary information about the id.
|
||||
*/
|
||||
public String toString() {
|
||||
return "["+type.toString()+":"+id+"]";
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
/** Specifies the type of an {@link Entity}.
|
||||
*/
|
||||
public enum EntityType {
|
||||
/** Represents an NPC entity.
|
||||
*/
|
||||
NPC,
|
||||
/** Represents the first Player.
|
||||
*/
|
||||
P1,
|
||||
/** Represents the second Player.
|
||||
*/
|
||||
P2,
|
||||
/** Represents a Rock entity.
|
||||
*/
|
||||
Rocks,
|
||||
/** Represents an InfinityStone entity.
|
||||
*/
|
||||
InfinityStones
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
|
||||
/** Represents an infinity stone {@link Entity}. Can only exist on the map.
|
||||
*/
|
||||
public class InfinityStone extends Entity {
|
||||
/** The {@link StoneType} of the infinity stone.
|
||||
*/
|
||||
public final StoneType type;
|
||||
|
||||
/** Constructs a new {@link InfinityStone}.
|
||||
* @param id The {@link EntityID} of the stone.
|
||||
* @param position The position of the stone.
|
||||
* @param type The {@link StoneType} of the stone.
|
||||
*/
|
||||
public InfinityStone(EntityID id, IntVector2 position, StoneType type) {
|
||||
super(id, position);
|
||||
this.type = type;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** Represents an inventory of 6 slots of {@link StoneType}s that can be manipulated.
|
||||
*/
|
||||
public class Inventory implements Iterable<StoneType> {
|
||||
/** The size of the inventory.
|
||||
*/
|
||||
private final int size = 6;
|
||||
|
||||
/** The content of the inventory.
|
||||
*/
|
||||
private final HashSet<StoneType> content = new HashSet<>(size);
|
||||
|
||||
/** Constructs a new {@link Inventory}.
|
||||
* @param content The starting content of the inventory.
|
||||
*/
|
||||
public Inventory(ArrayList<StoneType> content) {
|
||||
if(content.size() > size) {
|
||||
throw new IllegalArgumentException("Attempted to construct an inventory with more than "+size+" initial stones.");
|
||||
}
|
||||
|
||||
for(StoneType stone : content) {
|
||||
if(content.contains(stone)) {
|
||||
throw new IllegalArgumentException("Attempted to construct an inventory with duplicate entries.");
|
||||
}
|
||||
content.add(stone);
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs a new empty {@link Inventory}.
|
||||
*/
|
||||
public Inventory() {
|
||||
|
||||
}
|
||||
|
||||
/** Returns the number of free slots the inventory has.
|
||||
*/
|
||||
public int getFreeSlots() {
|
||||
return size - content.size();
|
||||
}
|
||||
|
||||
/** Checks if the inventory contains the given stone.
|
||||
* @param stone The {@link StoneType} to check for.
|
||||
*/
|
||||
public boolean hasStone(StoneType stone) {
|
||||
return content.contains(stone);
|
||||
}
|
||||
|
||||
/** Adds a stone to the inventory.
|
||||
* @param stone The {@link StoneType} to add.
|
||||
*/
|
||||
public void addStone(StoneType stone) {
|
||||
if(content.contains(stone)) {
|
||||
throw new IllegalArgumentException("Attempted to add a duplicate stone to an inventory.");
|
||||
}
|
||||
if(content.size() == size) {
|
||||
throw new IllegalArgumentException("Attempted to add a stone to a full inventory.");
|
||||
}
|
||||
|
||||
content.add(stone);
|
||||
}
|
||||
|
||||
/** Removes a stone from the inventory.
|
||||
* @param stone The {@link StoneType} to remove.
|
||||
*/
|
||||
public void removeStone(StoneType stone) {
|
||||
if(!content.contains(stone)) {
|
||||
throw new IllegalArgumentException("Attempted to remove a nonexistent stone from an inventory.");
|
||||
}
|
||||
|
||||
content.remove(stone);
|
||||
}
|
||||
|
||||
/** Iterates over the inventory.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<StoneType> iterator() {
|
||||
return content.iterator();
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** Represents an NPC inside the game.
|
||||
*/
|
||||
public class NPC extends Entity {
|
||||
/** The {@link Inventory} of the NPC.
|
||||
*/
|
||||
public final Inventory inventory;
|
||||
|
||||
/** Constructs a new {@link NPC}.
|
||||
* @param id The {@link EntityID} of the NPC.
|
||||
* @param position The position of the NPC.
|
||||
* @param inventory The starting inventory the NPC should have.
|
||||
*/
|
||||
public NPC(EntityID id, IntVector2 position, ArrayList<StoneType> inventory) {
|
||||
super(id, position);
|
||||
this.inventory = new Inventory(inventory);
|
||||
}
|
||||
|
||||
/** Constructs a new {@link NPC} with an empty inventory.
|
||||
* @param id The {@link EntityID} of the NPC.
|
||||
* @param position The position of the NPC.
|
||||
*/
|
||||
public NPC(EntityID id, IntVector2 position) {
|
||||
super(id, position);
|
||||
this.inventory = new Inventory();
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
/** Specifies the type of an {@link NPC}.
|
||||
*/
|
||||
public enum NPCType {
|
||||
/** Represents the Goose.
|
||||
*/
|
||||
Goose,
|
||||
/** Represents Stan Lee.
|
||||
*/
|
||||
Stan,
|
||||
/** Represents Thanos.
|
||||
*/
|
||||
Thanos
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
|
||||
/** Represents a rock entity on the map.
|
||||
*/
|
||||
public class Rock extends Entity {
|
||||
/** The maximum hp of the rock.
|
||||
*/
|
||||
public final int maxHP;
|
||||
|
||||
/** The current hp of the rock.
|
||||
*/
|
||||
private int hp;
|
||||
|
||||
/** Constructs a new {@link Rock}.
|
||||
* @param id The {@link EntityID} of the rock.
|
||||
* @param position The position of the rock.
|
||||
* @param hp The hp of the rock.
|
||||
*/
|
||||
public Rock(EntityID id, IntVector2 position, int hp) {
|
||||
super(id, position);
|
||||
this.maxHP = hp;
|
||||
this.hp = hp;
|
||||
}
|
||||
|
||||
public int getHp() {
|
||||
return hp;
|
||||
}
|
||||
|
||||
public void decreaseHp(int damage) {
|
||||
this.hp -= damage;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
/** Represents a stat property of a {@link Character}.
|
||||
*/
|
||||
public class Stat {
|
||||
/** The {@link StatType} of the stat.
|
||||
*/
|
||||
public final StatType type;
|
||||
|
||||
/** The maximum value of the stat.
|
||||
*/
|
||||
public final int max;
|
||||
|
||||
/** The current value of the stat.
|
||||
*/
|
||||
private int value;
|
||||
|
||||
/** Constructs a new {@link Stat} with the initial value set to the maximum value.
|
||||
* @param type The {@link StatType} of the stat.
|
||||
* @param max The maximum value of the stat.
|
||||
*/
|
||||
public Stat(StatType type, int max) {
|
||||
this.type = type;
|
||||
this.max = max;
|
||||
this.value = max;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void increaseValue(int value) {
|
||||
this.value += value;
|
||||
}
|
||||
|
||||
public void decreaseValue(int value) {
|
||||
this.value -= value;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
/** Specifies the type of a {@link Stat}.
|
||||
*/
|
||||
public enum StatType {
|
||||
/** Represents the life points of a character.
|
||||
*/
|
||||
HP,
|
||||
/** Represents the mana points of a character.
|
||||
*/
|
||||
MP,
|
||||
/** Represents thr action points of a character.
|
||||
*/
|
||||
AP
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.entities;
|
||||
|
||||
/** Specifies the type of an {@link InfinityStone}.
|
||||
*/
|
||||
public enum StoneType {
|
||||
SpaceStone,
|
||||
MindStone,
|
||||
RealityStone,
|
||||
PowerStone,
|
||||
TimeStone,
|
||||
SoulStone
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.events;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.json.MessageStructure;
|
||||
|
||||
/** Represents an abstract event sent inside a {@link MessageStructure} between client and server.
|
||||
*/
|
||||
public abstract class Event {
|
||||
//TODO: implement Event
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
/** Contains checksum calculations.
|
||||
*/
|
||||
class ChecksumCalculator {
|
||||
/** Compares a checksum to the checksum of a {@link GameState}.
|
||||
* @param state The state to check.
|
||||
* @param input the checksum to compare to.
|
||||
* @return Whether or not the checksum matches the state's checksum.
|
||||
*/
|
||||
public static boolean checkChecksum(GameState state, long input) {
|
||||
return calculateChecksum(state) == input;
|
||||
}
|
||||
|
||||
/** Calculates the corresponding checksum to a {@link GameState}.
|
||||
* @param state The state to check.
|
||||
* @return The checksum.
|
||||
*/
|
||||
public static long calculateChecksum(GameState state) {
|
||||
//TODO: implement ChecksumCalculator.calculateChecksum
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
import java.util.Observable;
|
||||
|
||||
/** Represents an event emitter for game events fired by a game instance.
|
||||
*/
|
||||
class EventEmitter extends Observable {
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||
|
||||
import java.util.Observer;
|
||||
|
||||
/** Represents a game instance.
|
||||
*/
|
||||
public class GameInstance {
|
||||
/** The private {@link GameState} of the instance.
|
||||
*/
|
||||
private final GameState _state;
|
||||
|
||||
/** The public view for the underlying {@link GameState} of the instance.
|
||||
*/
|
||||
public final GameStateView state;
|
||||
|
||||
/** The {@link GameStateManager} managing the {@link GameState} of the instance.
|
||||
*/
|
||||
private final GameStateManager manager;
|
||||
|
||||
/** The {@link EventEmitter} for {@link Event}s resulting from {@link Request}s.
|
||||
*/
|
||||
private final EventEmitter emitter = new EventEmitter();
|
||||
|
||||
/** Constructs a new {@link GameInstance}.
|
||||
*/
|
||||
public GameInstance(IntVector2 mapSize) {
|
||||
_state = new GameState(mapSize);
|
||||
this.state = new GameStateView(_state);
|
||||
manager = new GameStateManager(_state);
|
||||
}
|
||||
|
||||
/** Checks a checksum with the current one.
|
||||
* @param input The checksum to compare to.
|
||||
* @return Whether or not the checksum matches.
|
||||
*/
|
||||
public boolean checkChecksum(long input) {
|
||||
return ChecksumCalculator.checkChecksum(_state, input);
|
||||
}
|
||||
|
||||
/** Calculates the current checksum of the game state.
|
||||
* @return The calculated checksum.
|
||||
*/
|
||||
public long calculateChecksum() {
|
||||
return ChecksumCalculator.calculateChecksum(_state);
|
||||
}
|
||||
|
||||
/** Checks an array of {@link Request}s for validity and automatically applies them if valid.
|
||||
* @param requests The requests to check.
|
||||
* @return Whether or not the given set of requests was valid.
|
||||
*/
|
||||
public boolean checkRequestsAndApply(Request... requests) {
|
||||
if(manager.processRequests(requests, true)) {
|
||||
emit(manager.apply());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Checks an array of {@link Request}s for validity without applying it.
|
||||
* @param requests The requests to check.
|
||||
* @return Whether or not the given set of requests is valid.
|
||||
*/
|
||||
public boolean checkRequestsSilent(Request... requests) {
|
||||
return manager.processRequests(requests, false);
|
||||
}
|
||||
|
||||
/** Applies an array of {@link Event}s to the game state.
|
||||
* @param events The events to apply.
|
||||
*/
|
||||
public void applyEvents(Event... events) {
|
||||
manager.applyEvents(events);
|
||||
}
|
||||
|
||||
/** Adds an {@link Observer} for events.
|
||||
* @param observer The observer to add.
|
||||
*/
|
||||
public void addObserver(Observer observer) {
|
||||
emitter.addObserver(observer);
|
||||
}
|
||||
|
||||
/** Emits an array of {@link Event}s.
|
||||
* @param events The events to emit.
|
||||
*/
|
||||
private void emit(Event... events) {
|
||||
emitter.notifyObservers(events);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.Tuple;
|
||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/** Contains game logic handling.
|
||||
*/
|
||||
class GameLogic {
|
||||
/** Produces resulting {@link Event}s from a given {@link Request} independently of any {@link GameState}.
|
||||
* @return The list of resulting events.
|
||||
*/
|
||||
public static ArrayList<Event> executeRequest(Request request) {
|
||||
ArrayList<Event> result = new ArrayList<Event>();
|
||||
|
||||
//TODO: implement GameLogic.executeRequest
|
||||
|
||||
/* Example Code:
|
||||
switch (event.type) {
|
||||
case EventType.MeleeAttack:
|
||||
result.add(Event.Construct(EventType.APReduced, event.sourceEntity, event.ap));
|
||||
result.add(Event.Construct(EventType.DamageTaken, event.targetEntity, event.value));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Checks a {@link Request} for validity for a {@link GameState}.
|
||||
* @param state The game state to check on.
|
||||
* @param request The request to validate.
|
||||
* @return Whether or not the request is valid
|
||||
*/
|
||||
public static boolean checkRequest(GameState state, Request request) {
|
||||
//TODO: implement GameLogic.checkRequest
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Applies an {@link Event} to a {@link GameState}.
|
||||
* @param state The game state to apply to.
|
||||
* @param event The event to apply.
|
||||
*/
|
||||
public static void applyEvent(GameState state, Event event) {
|
||||
//TODO: implement GameLogic.applyEvent
|
||||
}
|
||||
|
||||
/** Checks a {@link GameState} for the current overtime win condition.
|
||||
* @param state The game state to check.
|
||||
* @return The {@link ParticipantType} that is currently winning the game according to overtime ruling.
|
||||
*/
|
||||
public static ParticipantType checkWinConditions(GameState state) {
|
||||
//TODO: GameLogic.checkWinConditions is kind of ugly
|
||||
|
||||
Tuple<ParticipantType, WinCondition> player1;
|
||||
Tuple<ParticipantType, WinCondition> player2;
|
||||
int value1;
|
||||
int value2;
|
||||
for(WinCondition condition: WinCondition.values()) {
|
||||
player1 = new Tuple<ParticipantType, WinCondition>(ParticipantType.Player1, condition);
|
||||
player2 = new Tuple<ParticipantType, WinCondition>(ParticipantType.Player2, condition);
|
||||
value1 = 0;
|
||||
value2 = 0;
|
||||
|
||||
if(state.winConditions.containsKey(player1)) {
|
||||
value1 = state.winConditions.get(player1);
|
||||
}
|
||||
if(state.winConditions.containsKey(player2)) {
|
||||
value2 = state.winConditions.get(player2);
|
||||
}
|
||||
|
||||
if(value1 > value2) {
|
||||
return ParticipantType.Player1;
|
||||
}
|
||||
if(value2 > value1) {
|
||||
return ParticipantType.Player2;
|
||||
}
|
||||
}
|
||||
|
||||
return ParticipantType.None;
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.Entity;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.EntityID;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.StoneType;
|
||||
import uulm.teamname.marvelous.gamelibrary.Tuple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/** Represents the state of a game instance.
|
||||
*/
|
||||
class GameState {
|
||||
/** The size of the map.
|
||||
*/
|
||||
public final IntVector2 mapSize;
|
||||
|
||||
/** The list of {@link Entity}'s inside the game.
|
||||
*/
|
||||
public ArrayList<Entity> entities;
|
||||
|
||||
/** The total amount of full turn cycles that occurred.
|
||||
*/
|
||||
public int roundNumber = 0;
|
||||
|
||||
/** The turn order of every character.
|
||||
*/
|
||||
public ArrayList<EntityID> turnOrder;
|
||||
|
||||
/** The total amount of turns that occurred.
|
||||
*/
|
||||
public int turnNumber = 0;
|
||||
|
||||
/** The {@link EntityID} of the active character.
|
||||
*/
|
||||
public EntityID activeCharacter;
|
||||
|
||||
/** Whether or not the game was won.
|
||||
*/
|
||||
public boolean won = false;
|
||||
|
||||
/** The global cooldown of every infinity stone.
|
||||
*/
|
||||
public HashMap<StoneType, Float> stoneCooldown;
|
||||
|
||||
/** The store of the {@link WinCondition} data for every win condition for each player.
|
||||
*/
|
||||
public HashMap<Tuple<ParticipantType, WinCondition>, Integer> winConditions;
|
||||
|
||||
/** Constructs a new {@link GameState}.
|
||||
* @param mapSize The size of the map.
|
||||
*/
|
||||
public GameState(IntVector2 mapSize) {
|
||||
this.mapSize = mapSize;
|
||||
}
|
||||
|
||||
/** Clones the state into a new {@link GameState} object.
|
||||
* @return The cloned game state.
|
||||
*/
|
||||
public GameState snapshot() {
|
||||
//TODO: implement GameState.snapshot
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** Represents manager for a game state.
|
||||
*/
|
||||
class GameStateManager {
|
||||
/** The managed {@link GameState}.
|
||||
*/
|
||||
private final GameState state;
|
||||
|
||||
/** The queue of {@link Event}s to be applied during {@link Request} processing.
|
||||
*/
|
||||
private final ArrayDeque<Event> queue = new ArrayDeque<Event>();
|
||||
|
||||
/** Constructs a new {@link GameStateManager}.
|
||||
* @param state A reference to the state to be managed.
|
||||
*/
|
||||
public GameStateManager(GameState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/** Checks a list of {@link Request}s for validity and optionally produces resulting {@link Event}s.
|
||||
* @param requests The requests to check.
|
||||
* @param apply True if resulting events should be stored for later application.
|
||||
*/
|
||||
public boolean processRequests(Request[] requests, boolean apply) {
|
||||
GameState snapshot = state.snapshot();
|
||||
|
||||
for(Request request: requests) {
|
||||
if (GameLogic.checkRequest(snapshot, request)) {
|
||||
ArrayList<Event> result = GameLogic.executeRequest(request);
|
||||
if(apply) {
|
||||
queue.addAll(result);
|
||||
}
|
||||
}else {
|
||||
queue.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Applies an array of {@link Event}s to the game state.
|
||||
* @param events The events to apply.
|
||||
*/
|
||||
public void applyEvents(Event[] events) {
|
||||
for(Event event: events) {
|
||||
GameLogic.applyEvent(state, event);
|
||||
}
|
||||
}
|
||||
|
||||
/** Applies the result of the last processRequests call.
|
||||
* @return A list of applied events.
|
||||
*/
|
||||
public Event[] apply() {
|
||||
Event[] toReturn = new Event[queue.size()];
|
||||
Event current;
|
||||
int i = 0;
|
||||
while ((current = queue.poll()) != null) {
|
||||
GameLogic.applyEvent(state, current);
|
||||
toReturn[i++] = current;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.Entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** Represents a game state view containing getters for all the properties of a {@link GameState}.
|
||||
*/
|
||||
public class GameStateView {
|
||||
/** The managed {@link GameState}.
|
||||
*/
|
||||
private final GameState state;
|
||||
|
||||
/** Constructs a new {@link GameStateView}.
|
||||
* @param state A reference to the state to be viewable.
|
||||
*/
|
||||
public GameStateView(GameState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
//TODO: add immutable getters for all state properties
|
||||
|
||||
public ArrayList<Entity> getEntities() {
|
||||
return new ArrayList<>(state.entities);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
/** Specifies a participant type.
|
||||
*/
|
||||
public enum ParticipantType {
|
||||
None,
|
||||
Player1,
|
||||
Player2,
|
||||
Spectator
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.gamelogic;
|
||||
|
||||
/** Specifies a win condition. The order is important here.
|
||||
*/
|
||||
enum WinCondition {
|
||||
/** The maximum amount of total infinity stones the player had at a time.
|
||||
*/
|
||||
MaxStones,
|
||||
/** The total amount of enemy characters the player knocked out.
|
||||
*/
|
||||
TotalKnockouts,
|
||||
/** The total amount of damage the player did to enemy characters.
|
||||
*/
|
||||
TotalDamage
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.json;
|
||||
|
||||
public class CharacterConfiguration {
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.json;
|
||||
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
|
||||
/** Contains JSON encoding and decoding.
|
||||
*/
|
||||
public class JSON {
|
||||
/** Deserializes an incoming network message into a {@link MessageStructure}.
|
||||
* @param input The JSON to deserialize.
|
||||
* @return The parsed message.
|
||||
*/
|
||||
public static MessageStructure[] parse(String input) throws ExecutionControl.NotImplementedException {
|
||||
//TODO: implement JSON.parse
|
||||
throw new ExecutionControl.NotImplementedException("JSON.parse is not implemented");
|
||||
}
|
||||
|
||||
/** Serializes a {@link MessageStructure} into a JSON string.
|
||||
* @param input The message to serialize.
|
||||
* @return The message as JSON.
|
||||
*/
|
||||
public static String stringify(MessageStructure input) throws ExecutionControl.NotImplementedException {
|
||||
//TODO: implement JSON.stringify
|
||||
throw new ExecutionControl.NotImplementedException("JSON.stringify is not implemented");
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.json;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/** Represents a message sent between client and server and contains all possible data.
|
||||
*/
|
||||
public class MessageStructure {
|
||||
//TODO: revise MessageStructure according to actual standard document
|
||||
|
||||
/** The list of {@link Event}s sent inside the message.
|
||||
*/
|
||||
public Event[] events;
|
||||
|
||||
/** The checksum of the current game state at the time the message was sent.
|
||||
*/
|
||||
public int checksum;
|
||||
|
||||
/** The type of the custom content sent with the message.
|
||||
*/
|
||||
public String customContentType;
|
||||
|
||||
/** The decoded contents of the custom content sent.
|
||||
*/
|
||||
public HashMap<String, Object> customContent;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.requests;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.json.MessageStructure;
|
||||
|
||||
/** Represents an abstract request sent inside a {@link MessageStructure} between client and server.
|
||||
*/
|
||||
public abstract class Request {
|
||||
//TODO: implement Request
|
||||
}
|
Reference in New Issue
Block a user