diff --git a/flatbuffers-compiler/bin/flatc.exe b/flatbuffers-compiler/bin/flatc.exe new file mode 100644 index 00000000..38563fd3 Binary files /dev/null and b/flatbuffers-compiler/bin/flatc.exe differ diff --git a/flatbuffers-compiler/bin/linux/flatc.zip b/flatbuffers-compiler/bin/linux/flatc.zip new file mode 100644 index 00000000..ef1b8cb3 Binary files /dev/null and b/flatbuffers-compiler/bin/linux/flatc.zip differ diff --git a/flatbuffers-compiler/bin/osx/flatc.zip b/flatbuffers-compiler/bin/osx/flatc.zip new file mode 100644 index 00000000..3e489556 Binary files /dev/null and b/flatbuffers-compiler/bin/osx/flatc.zip differ diff --git a/flatbuffers-compiler/bin/windows/flatc.zip b/flatbuffers-compiler/bin/windows/flatc.zip new file mode 100644 index 00000000..368e5d24 Binary files /dev/null and b/flatbuffers-compiler/bin/windows/flatc.zip differ diff --git a/flatbuffers-compiler/example/src/main/java/example/Color.java b/flatbuffers-compiler/example/src/main/java/example/Color.java new file mode 100644 index 00000000..fbe57998 --- /dev/null +++ b/flatbuffers-compiler/example/src/main/java/example/Color.java @@ -0,0 +1,16 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package example; + +@SuppressWarnings("unused") +public final class Color { + private Color() { } + public static final byte Red = 0; + public static final byte Green = 1; + public static final byte Blue = 2; + + public static final String[] names = { "Red", "Green", "Blue", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/flatbuffers-compiler/example/src/main/java/example/Equipment.java b/flatbuffers-compiler/example/src/main/java/example/Equipment.java new file mode 100644 index 00000000..3a022d17 --- /dev/null +++ b/flatbuffers-compiler/example/src/main/java/example/Equipment.java @@ -0,0 +1,15 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package example; + +@SuppressWarnings("unused") +public final class Equipment { + private Equipment() { } + public static final byte NONE = 0; + public static final byte Weapon = 1; + + public static final String[] names = { "NONE", "Weapon", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/flatbuffers-compiler/example/src/main/java/example/Monster.java b/flatbuffers-compiler/example/src/main/java/example/Monster.java new file mode 100644 index 00000000..46e6b7f0 --- /dev/null +++ b/flatbuffers-compiler/example/src/main/java/example/Monster.java @@ -0,0 +1,69 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package example; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Monster extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_8(); } + public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); } + public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public example.Vec3 pos() { return pos(new example.Vec3()); } + public example.Vec3 pos(example.Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + public short mana() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 150; } + public short hp() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 100; } + public String name() { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(10, 1); } + public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 10, 1); } + public int inventory(int j) { int o = __offset(14); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; } + public int inventoryLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } + public ByteVector inventoryVector() { return inventoryVector(new ByteVector()); } + public ByteVector inventoryVector(ByteVector obj) { int o = __offset(14); return o != 0 ? obj.__assign(__vector(o), bb) : null; } + public ByteBuffer inventoryAsByteBuffer() { return __vector_as_bytebuffer(14, 1); } + public ByteBuffer inventoryInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 14, 1); } + public byte color() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) : 2; } + public example.Weapon weapons(int j) { return weapons(new example.Weapon(), j); } + public example.Weapon weapons(example.Weapon obj, int j) { int o = __offset(18); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int weaponsLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } + public example.Weapon.Vector weaponsVector() { return weaponsVector(new example.Weapon.Vector()); } + public example.Weapon.Vector weaponsVector(example.Weapon.Vector obj) { int o = __offset(18); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } + public byte equippedType() { int o = __offset(20); return o != 0 ? bb.get(o + bb_pos) : 0; } + public Table equipped(Table obj) { int o = __offset(22); return o != 0 ? __union(obj, o + bb_pos) : null; } + + public static void startMonster(FlatBufferBuilder builder) { builder.startTable(10); } + public static void addPos(FlatBufferBuilder builder, int posOffset) { builder.addStruct(0, posOffset, 0); } + public static void addMana(FlatBufferBuilder builder, short mana) { builder.addShort(1, mana, 150); } + public static void addHp(FlatBufferBuilder builder, short hp) { builder.addShort(2, hp, 100); } + public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(3, nameOffset, 0); } + public static void addInventory(FlatBufferBuilder builder, int inventoryOffset) { builder.addOffset(5, inventoryOffset, 0); } + public static int createInventoryVector(FlatBufferBuilder builder, byte[] data) { return builder.createByteVector(data); } + public static int createInventoryVector(FlatBufferBuilder builder, ByteBuffer data) { return builder.createByteVector(data); } + public static void startInventoryVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } + public static void addColor(FlatBufferBuilder builder, byte color) { builder.addByte(6, color, 2); } + public static void addWeapons(FlatBufferBuilder builder, int weaponsOffset) { builder.addOffset(7, weaponsOffset, 0); } + public static int createWeaponsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startWeaponsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addEquippedType(FlatBufferBuilder builder, byte equippedType) { builder.addByte(8, equippedType, 0); } + public static void addEquipped(FlatBufferBuilder builder, int equippedOffset) { builder.addOffset(9, equippedOffset, 0); } + public static int endMonster(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset); } + public static void finishSizePrefixedMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset); } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Monster get(int j) { return get(new Monster(), j); } + public Monster get(Monster obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/flatbuffers-compiler/example/src/main/java/example/Vec3.java b/flatbuffers-compiler/example/src/main/java/example/Vec3.java new file mode 100644 index 00000000..890bb2b2 --- /dev/null +++ b/flatbuffers-compiler/example/src/main/java/example/Vec3.java @@ -0,0 +1,34 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package example; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Vec3 extends Struct { + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public float x() { return bb.getFloat(bb_pos + 0); } + public float y() { return bb.getFloat(bb_pos + 4); } + public float z() { return bb.getFloat(bb_pos + 8); } + + public static int createVec3(FlatBufferBuilder builder, float x, float y, float z) { + builder.prep(4, 12); + builder.putFloat(z); + builder.putFloat(y); + builder.putFloat(x); + return builder.offset(); + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Vec3 get(int j) { return get(new Vec3(), j); } + public Vec3 get(Vec3 obj, int j) { return obj.__assign(__element(j), bb); } + } +} + diff --git a/flatbuffers-compiler/example/src/main/java/example/Weapon.java b/flatbuffers-compiler/example/src/main/java/example/Weapon.java new file mode 100644 index 00000000..4d22ba24 --- /dev/null +++ b/flatbuffers-compiler/example/src/main/java/example/Weapon.java @@ -0,0 +1,47 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package example; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Weapon extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_8(); } + public static Weapon getRootAsWeapon(ByteBuffer _bb) { return getRootAsWeapon(_bb, new Weapon()); } + public static Weapon getRootAsWeapon(ByteBuffer _bb, Weapon obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Weapon __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public String name() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } + public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 1); } + public short damage() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 0; } + + public static int createWeapon(FlatBufferBuilder builder, + int nameOffset, + short damage) { + builder.startTable(2); + Weapon.addName(builder, nameOffset); + Weapon.addDamage(builder, damage); + return Weapon.endWeapon(builder); + } + + public static void startWeapon(FlatBufferBuilder builder) { builder.startTable(2); } + public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } + public static void addDamage(FlatBufferBuilder builder, short damage) { builder.addShort(1, damage, 0); } + public static int endWeapon(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Weapon get(int j) { return get(new Weapon(), j); } + public Weapon get(Weapon obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/flatbuffers-compiler/pom.xml b/flatbuffers-compiler/pom.xml new file mode 100644 index 00000000..eb472547 --- /dev/null +++ b/flatbuffers-compiler/pom.xml @@ -0,0 +1,59 @@ + + 4.0.0 + + com.github.davidmoten + flatbuffers-parent + 2.0.9-SNAPSHOT + + flatbuffers-compiler + pom + Compressed archive of binaries for flatbuffers particularly flatc for generating classes. Multiple platforms supported vi different classifications. + + + + + maven-antrun-plugin + 3.1.0 + + + generate-resources + + + + + + + + + + + + run + + + + + + maven-assembly-plugin + 3.5.0 + + + src/assembly/linux.xml + src/assembly/osx.xml + src/assembly/windows.xml + + + + + make-assembly + package + + single + + + + + + + + diff --git a/flatbuffers-compiler/src/assembly/linux.xml b/flatbuffers-compiler/src/assembly/linux.xml new file mode 100644 index 00000000..6225dff5 --- /dev/null +++ b/flatbuffers-compiler/src/assembly/linux.xml @@ -0,0 +1,16 @@ + + distribution-linux + false + + tar.gz + + + + ${project.build.directory}/linux + /bin + + + diff --git a/flatbuffers-compiler/src/assembly/osx.xml b/flatbuffers-compiler/src/assembly/osx.xml new file mode 100644 index 00000000..477c86e1 --- /dev/null +++ b/flatbuffers-compiler/src/assembly/osx.xml @@ -0,0 +1,16 @@ + + distribution-osx + false + + tar.gz + + + + ${project.build.directory}/osx + /bin + + + diff --git a/flatbuffers-compiler/src/assembly/windows.xml b/flatbuffers-compiler/src/assembly/windows.xml new file mode 100644 index 00000000..13200375 --- /dev/null +++ b/flatbuffers-compiler/src/assembly/windows.xml @@ -0,0 +1,16 @@ + + distribution-windows + false + + zip + + + + ${project.build.directory}/windows + /bin + + + diff --git a/pom.xml b/pom.xml index 8fd0476c..924c7f10 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,9 @@ UTF-8 5.8.2 1.8.10 + + ${basedir}/src/main/fbs + ${project.build.directory}/generated-sources/java @@ -48,6 +51,13 @@ + + + com.google.flatbuffers + flatbuffers-java + 2.0.8 + + org.junit.jupiter junit-jupiter-api @@ -80,6 +90,13 @@ + + + kr.motd.maven + os-maven-plugin + 1.7.1 + + org.openjfx @@ -102,6 +119,77 @@ + + + org.apache.maven.plugins + maven-dependency-plugin + 2.10 + + + unpack + generate-sources + + unpack + + + + + com.github.davidmoten + flatbuffers-compiler + 2.0.3.1 + tar.gz + distribution-linux + true + ${project.build.directory} + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + exec + + generate-sources + + + + ${project.build.directory}/bin/flatc + ${fbs.sources} + + --java + --gen-mutable + -o + ${fbs.generated.sources} + monster.fbs + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.1.0 + + + add-source + generate-sources + + add-source + + + + ${fbs.generated.sources} + + + + + org.jacoco diff --git a/src/main/fbs/spawn.fbs b/src/main/fbs/spawn.fbs new file mode 100644 index 00000000..b1fd0864 --- /dev/null +++ b/src/main/fbs/spawn.fbs @@ -0,0 +1,19 @@ +include "update.fbs"; +//Данные для обновления состояния объектов +namespace ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +enum ActionStatus:byte{ CREATED=0, // для клиента + APPROVED=1, // принят сервером или им создан + REFUSED=2 // отказано + } +table NewEntityData{ + type:string;//В будущем лучше раздать id всем Entity которые спавнятся на фабриках + seed:int; + state:EntityStateData; +} + +table SpawnActionData { + data:NewEntityData; +} + +root_type SpawnActionData; \ No newline at end of file diff --git a/src/main/fbs/update.fbs b/src/main/fbs/update.fbs new file mode 100644 index 00000000..0f6e6788 --- /dev/null +++ b/src/main/fbs/update.fbs @@ -0,0 +1,21 @@ +//./flatc.exe -j -o <куда> <*.fbs> +//Данные для обновления состояния объектов +namespace ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +struct Point2D { + x:double; + y:double; +} + +table EntityStateData { + id:int; + pos:Point2D; + rot:Point2D; + active_weapon:int; +} + +table EntityStateDataList{ + list:[EntityStateData]; +} + +root_type EntityStateDataList; \ No newline at end of file diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/App.java b/src/main/java/ru/nsu/fit/dib/projectdib/App.java index 15b88f0d..52c61c02 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/App.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/App.java @@ -3,18 +3,11 @@ import com.almasb.fxgl.app.GameApplication; import com.almasb.fxgl.app.GameSettings; import com.almasb.fxgl.entity.Entity; -import java.net.InetSocketAddress; -import java.util.List; import ru.nsu.fit.dib.projectdib.initapp.GameInitializer; import ru.nsu.fit.dib.projectdib.initapp.InputListener; import ru.nsu.fit.dib.projectdib.initapp.PhysicsLoader; import ru.nsu.fit.dib.projectdib.initapp.SettingsLoader; -import ru.nsu.fit.dib.projectdib.newMultiplayer.config.ClientConfig; -import ru.nsu.fit.dib.projectdib.newMultiplayer.config.ServerConfig; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.MCServer; -import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientThread; -import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ServerThread; + /** * Основной класс игры. @@ -69,29 +62,44 @@ protected void initPhysics() { protected void onPreInit() { } + /** * Инициализация игры. */ @Override protected void initGame() { - - ServerConfig.init(); - ClientConfig.init(); - ServerConfig.addClientAddresses(List.of(new InetSocketAddress("localhost", 9090))); - ServerThread serverThread = new ServerThread(MCServer.getReceiver(), MCServer.getSender(), MCServer.getClientAddresses()); - ServerConfig.addServerThread(serverThread); - - ClientConfig.addServerAddress(new InetSocketAddress("localhost", 8080)); - ClientThread clientThread = new ClientThread(MCClient.getReceiver(), MCClient.getSender(), MCClient.getServerAddress()); - ClientConfig.addClientThread(clientThread); - - serverThread.start(); - clientThread.start(); - - + /* + switch (gameMode){ + case SERVER, SINGLE -> { + ServerSocket serverSocket; + Map clientSockets = new HashMap<>(); + try { + serverSocket = new ServerSocket(8080); + } catch (IOException e) { + throw new RuntimeException(e); + } + try { + System.out.println("Подключение"); + new Thread(()->initClient("localhost")).start(); + for (int i = 1; i < 3; i++) { + Socket client = serverSocket.accept(); + //отправляем клиенту его id + client.getOutputStream().write(i); + clientSockets.put(i, client); + new ServerReceiverThread(client).start(); + System.out.println("Подключено"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + ServerConfig.addClientSockets(clientSockets); + ServerConfig.init(); + } + case CLIENT -> initClient("192.168.43.8"); + }*/ GameInitializer gameInitializer = new GameInitializer(); gameInitializer.run(); inputListener.initialize(gameInitializer.getPlayer()); - player=gameInitializer.getPlayer(); + player = gameInitializer.getPlayer(); } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/Factory.java b/src/main/java/ru/nsu/fit/dib/projectdib/Factory.java index 47d6a6f6..cb09e382 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/Factory.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/Factory.java @@ -26,6 +26,7 @@ import com.almasb.fxgl.texture.AnimatedTexture; import com.almasb.fxgl.texture.AnimationChannel; import com.almasb.fxgl.ui.ProgressBar; +import com.fasterxml.jackson.databind.node.ObjectNode; import javafx.geometry.Point2D; import javafx.geometry.Rectangle2D; import javafx.scene.image.Image; @@ -37,6 +38,7 @@ import ru.nsu.fit.dib.projectdib.data.ProjectConfig; import ru.nsu.fit.dib.projectdib.data.RandomCharacterSystem; import ru.nsu.fit.dib.projectdib.entity.components.CreatureComponent; +import ru.nsu.fit.dib.projectdib.entity.components.DataComponent; import ru.nsu.fit.dib.projectdib.entity.components.HeroComponent; import ru.nsu.fit.dib.projectdib.entity.creatures.Creature; import ru.nsu.fit.dib.projectdib.entity.components.PlayerChaseComponent; @@ -52,6 +54,7 @@ import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.modules.TextureModule; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.modules.WeaponModule; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; /** * Class Factory for making Entities. @@ -61,37 +64,46 @@ public class Factory implements EntityFactory { /** * Creates Hero and heroes weapon. * - * @param heroType type of hero - * @param position position + * @param heroType type of hero + * @param position position * @param isClientHero true if client hero - * @param seed hero seed + * @param seed hero seed * @return pair of entity Hero and Weapon */ - public static Pair spawnHero(HeroType heroType,Point2D position, Boolean isClientHero,Integer seed){ + public static Entity spawnHero(HeroType heroType, Point2D position, Boolean isClientHero, + Integer id, Integer seed) { SpawnData sd = new SpawnData(position); - sd.put("clientHero",isClientHero); - sd.put("creature", HeroesFactory.newHero(heroType,seed)); + sd.put("owner", id); + sd.put("creature", HeroesFactory.newHero(heroType, seed)); + sd.put("id", id); Entity hero = spawn("player", sd); hero.setScaleUniform(0.75); - SpawnData weaponSD = new SpawnData(position); - weaponSD.put("weapon", hero.getComponent(HeroComponent.class).getCreature().getModule( - CreatureWeaponModule.class).getActiveWeapon()); - Entity weapon = spawn("weapon",weaponSD); - return new Pair<>(hero,weapon); + return hero; + } + + public static Entity spawnStandardWeapon(Integer id, Integer ownerID, Entity bindedEntity) { + SpawnData sd = new SpawnData(bindedEntity.getPosition()); + sd.put("id", id); + sd.put("owner", ownerID); + sd.put("weapon", bindedEntity.getComponent(HeroComponent.class).getCreature() + .getModule(CreatureWeaponModule.class).getActiveWeapon()); + return spawn("weapon", sd); } /** * Creates weapon. * * @param weaponType type of weapon - * @param position position + * @param position position * @return weapon entity */ - public static Entity spawnWeapon(Weapons weaponType,Point2D position){ + public static Entity spawnWeapon(Weapons weaponType, Point2D position, Integer id) { SpawnData sd = new SpawnData(position); + sd.put("id", id); sd.put("weapon", WeaponFactory.getWeapon(weaponType)); return spawn("weapon", sd); } + /** * Entity Player. * @@ -101,15 +113,24 @@ public static Entity spawnWeapon(Weapons weaponType,Point2D position){ @Spawns("player") public Entity newPlayer(SpawnData data) { Creature creature = data.get("creature"); + PhysicsComponent physics = new PhysicsComponent(); physics.setBodyType(BodyType.DYNAMIC); physics.setFixtureDef(new FixtureDef().friction(0.3f)); - HeroComponent heroComponent = new HeroComponent(creature,new Point2D(50,180)); - if (data.get("clientHero")) heroComponent.bindDirectionView(entity -> getInput().getVectorToMouse(entity.getPosition().add(new Point2D(80, 160)))); - else heroComponent.bindDirectionView(entity ->new Point2D(0,0)); + + HeroComponent heroComponent = new HeroComponent(creature, new Point2D(50, 180)); + if (data.get("owner") == MCClient.getClientId()) { + heroComponent.bindDirectionView( + entity -> getInput().getVectorToMouse(entity.getPosition().add(new Point2D(80, 160)))); + } else { + heroComponent.bindDirectionView(entity -> new Point2D(0, 0)); + } creature.getModule(JFXModule.class).setComponent(heroComponent); + + DataComponent dataComponent = new DataComponent(EntityType.PLAYER, data.get("owner"), + data.get("id")); //HeroSpecs specs = new HeroSpecs("1", "bow", "ak", 450.0, "player.png"); - return entityBuilder() + Entity entity = entityBuilder() .from(data) .type(EntityType.PLAYER) //.viewWithBBox(texture("weapon_" + playerMovingComponent.getCurrentWeapon() + ".png", 150,200)) @@ -117,13 +138,40 @@ public Entity newPlayer(SpawnData data) { .anchorFromCenter() .with(physics) .with(heroComponent) + .with(dataComponent) .with(new CellMoveComponent(30, 30, 85)) .with(new AStarMoveComponent(new LazyValue<>(() -> geto("grid")))) //.with(new ChunkLoaderComponent(new ChunkLoader(wallMapper))) .collidable() .build(); + while (!entity.hasComponent(DataComponent.class)); + return entity; } + @Spawns("weapon") + public Entity Weapon(SpawnData data) { + Weapon weapon = data.get("weapon"); + ImageView iv = imageViewFromSpriteSheet(weapon.getModule(TextureModule.class).getTexturePath(), + weapon.getModule(TextureModule.class).getWeaponID(), + weapon.getModule(TextureModule.class).getImageWidht(), + weapon.getModule(TextureModule.class).getImageHeight(), ProjectConfig._WEAPON_COLUMNS); + WeaponComponent weaponComponent = new WeaponComponent(weapon); + weapon.getModule(TextureModule.class).setComponent(weaponComponent); + + DataComponent dataComponent = new DataComponent(EntityType.WEAPON, data.get("owner"), + data.get("id")); + Entity entity = entityBuilder(data) + .from(data) + .type(EntityType.WEAPON) + .viewWithBBox(iv) + .bbox(new HitBox(BoundingShape.box(75, 20))) + .with(new CollidableComponent(true)) + .with(weaponComponent) + .with(dataComponent) + .build(); + while (!entity.hasComponent(DataComponent.class)); + return entity; + } @Spawns("platform") public Entity platform(SpawnData data) { @@ -252,72 +300,16 @@ public Entity newProjectile(SpawnData data) { .collidable() .build(); } - /* - @Spawns("bow") - public Entity newBow(SpawnData data) { - return entityBuilder(data) - .from(data) - .type(EntityType.BOW) - .viewWithBBox(texture("red_bow.png", 15, 50)) - .bbox(new HitBox(BoundingShape.box(50, 15))) - .with(new CollidableComponent(true)) - .build(); - } - - @Spawns("ak") - public Entity newAK(SpawnData data) { - return entityBuilder(data) - .from(data) - .type(EntityType.AK) - .viewWithBBox(texture("weapon_ak.png", 75, 20)) - .bbox(new HitBox(BoundingShape.box(75, 20))) - .with(new CollidableComponent(true)) - .build(); - } - @Spawns("player") - public Entity newPlayer(SpawnData data) { - PhysicsComponent physics = new PhysicsComponent(); - physics.setBodyType(BodyType.DYNAMIC); - physics.setFixtureDef(new FixtureDef().friction(0.3f)); - HeroSpecs specs = new HeroSpecs("1", "bow", "ak", 450.0, "player.png"); - return entityBuilder() - .from(data) - .type(EntityType.PLAYER) - //.viewWithBBox(texture("weapon_" + playerMovingComponent.getCurrentWeapon() + ".png", 150,200)) - .bbox(new HitBox(new Point2D(30, 220), BoundingShape.box(100, 100))) - .anchorFromCenter() - .with(physics) - .with(new PlayerMovingComponent(specs,new Point2D(50,180))) - .with(new CellMoveComponent(30, 30, 85)) - .with(new AStarMoveComponent(new LazyValue<>(() -> geto("grid")))) - //.with(new ChunkLoaderComponent(new ChunkLoader(wallMapper))) - .collidable() - .build(); - } - */ - @Spawns("weapon") - public Entity Weapon(SpawnData data) { - Weapon weapon = data.get("weapon"); - ImageView iv = imageViewFromSpriteSheet(weapon.getModule(TextureModule.class).getTexturePath(),weapon.getModule(TextureModule.class).getWeaponID(), - weapon.getModule(TextureModule.class).getImageWidht(),weapon.getModule(TextureModule.class).getImageHeight(), ProjectConfig._WEAPON_COLUMNS); - //iv.setRotate(90); - WeaponComponent weaponComponent = new WeaponComponent(weapon); - weapon.getModule(TextureModule.class).setComponent(weaponComponent); - return entityBuilder(data) - .from(data) - .type(EntityType.WEAPON) - .viewWithBBox(iv) - .bbox(new HitBox(BoundingShape.box(75, 20))) - .with(new CollidableComponent(true)) - .with(weaponComponent) - .build(); - } - ImageView imageViewFromSpriteSheet(String path, int number, int spriteWidth, int spriteHeight,int columns){ - ImageView iv = new ImageView(new Image(path)); - iv.setViewport(new Rectangle2D(spriteWidth*(number%columns),spriteHeight*(number/columns),spriteWidth,spriteHeight)); + ImageView imageViewFromSpriteSheet(Image img, int number, int spriteWidth, int spriteHeight, + int columns) { + ImageView iv = new ImageView(img); + iv.setViewport( + new Rectangle2D(spriteWidth * (number % columns), spriteHeight * (number / columns), + spriteWidth, spriteHeight)); return iv; } + /** * Entity Enemy. * diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/connecting/ClientConnection.java b/src/main/java/ru/nsu/fit/dib/projectdib/connecting/ClientConnection.java deleted file mode 100644 index 86617d5f..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/connecting/ClientConnection.java +++ /dev/null @@ -1,42 +0,0 @@ -package ru.nsu.fit.dib.projectdib.connecting; - - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.SocketTimeoutException; - -public class ClientConnection { - - private final InetAddress host; - - private final int port; - - private final DatagramSocket ds; - - public ClientConnection(InetAddress host, int port, DatagramSocket ds) { - this.host = host; - this.port = port; - this.ds = ds; - } - - /** - * При вызове лучше ловить SocketTimeoutException - * - * @throws SocketTimeoutException ошибка - */ - public void connect(int timeout) throws SocketTimeoutException { - byte[] hello = "hello".getBytes(); - DatagramPacket outPack = new DatagramPacket(hello, hello.length, host, port); - DatagramPacket inPack = new DatagramPacket(new byte[5], 5); - try { - ds.setSoTimeout(timeout); - ds.send(outPack); - ds.receive(inPack); - } catch (IOException e) { - throw new RuntimeException(e); - } - - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/connecting/ServerConnection.java b/src/main/java/ru/nsu/fit/dib/projectdib/connecting/ServerConnection.java deleted file mode 100644 index 7b7363d3..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/connecting/ServerConnection.java +++ /dev/null @@ -1,37 +0,0 @@ -package ru.nsu.fit.dib.projectdib.connecting; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.SocketTimeoutException; - -public class ServerConnection { - - private final DatagramSocket ds; - - public ServerConnection(DatagramSocket ds) { - this.ds = ds; - } - - /** - * Подключение. - * - * @return адрес подключенного. - */ - public SocketAddress accept(int timeout) throws SocketTimeoutException { - byte[] hello = "hello".getBytes(); - DatagramPacket inPack = new DatagramPacket(new byte[5], 5); - try { - ds.setSoTimeout(timeout); - ds.receive(inPack); - DatagramPacket outPack = new DatagramPacket(hello, hello.length, inPack.getAddress(), - inPack.getPort()); - ds.send(outPack); - return new InetSocketAddress(inPack.getAddress(), inPack.getPort()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/connecting/tasks/ClientConnectionTask.java b/src/main/java/ru/nsu/fit/dib/projectdib/connecting/tasks/ClientConnectionTask.java new file mode 100644 index 00000000..dc33cdfb --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/connecting/tasks/ClientConnectionTask.java @@ -0,0 +1,35 @@ +package ru.nsu.fit.dib.projectdib.connecting.tasks; + +import java.io.IOException; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketTimeoutException; +import java.util.function.Supplier; +import ru.nsu.fit.dib.projectdib.newMultiplayer.config.ClientConfig; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; + +public class ClientConnectionTask implements Supplier { + + private final SocketAddress serverAddress; + + public ClientConnectionTask(SocketAddress serverAddress) { + this.serverAddress = serverAddress; + } + + /** + * Выкидывает SocketTimeoutException при неправильном адресе + */ + @Override + public Socket get() { + Socket socket = new Socket(); + ClientConfig.addClientSocket(socket); + try { + socket.connect(serverAddress, 1000); + ClientConfig.addClientId(socket.getInputStream().read()); + } catch (Exception e) { + return null; + } + ClientConfig.init(); + return socket; + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/connecting/tasks/ServerConnectionTask.java b/src/main/java/ru/nsu/fit/dib/projectdib/connecting/tasks/ServerConnectionTask.java index c46e3bf4..564c59a6 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/connecting/tasks/ServerConnectionTask.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/connecting/tasks/ServerConnectionTask.java @@ -1,27 +1,34 @@ package ru.nsu.fit.dib.projectdib.connecting.tasks; -import java.net.DatagramSocket; -import java.net.SocketAddress; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; -import ru.nsu.fit.dib.projectdib.connecting.ServerConnection; +import ru.nsu.fit.dib.projectdib.data.ProjectConfig; +import ru.nsu.fit.dib.projectdib.newMultiplayer.config.ServerConfig; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.MCServer; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ServerReceiverThread; /** * Задание которое должно выполняться в CompletableFuture * Используется собственный interrupt для завершения */ -public class ServerConnectionTask implements Supplier> { - - private final DatagramSocket ds; +public class ServerConnectionTask implements Supplier> { private volatile boolean interrupt = false; - private final List socketAddressList = new ArrayList<>(); + private int lastClientId = 1; + + private final Map clientSockets = new ConcurrentHashMap<>(); - public ServerConnectionTask(DatagramSocket ds) { - this.ds = ds; + public Map getClientSockets() { + return clientSockets; } public void interrupt() { @@ -29,13 +36,31 @@ public void interrupt() { } @Override - public List get() { - ServerConnection serverConnection = new ServerConnection(ds); + public Map get() { + ServerSocket serverSocket; + try { + serverSocket = new ServerSocket(ProjectConfig.SERVER_PORT); + serverSocket.setSoTimeout(100); + } catch (IOException e) { + throw new RuntimeException(e); + } + CompletableFuture.supplyAsync( + new ClientConnectionTask(new InetSocketAddress("localhost", ProjectConfig.SERVER_PORT))); + ServerConfig.init(); while (!interrupt) { try { - socketAddressList.add(serverConnection.accept(1000)); - } catch (SocketTimeoutException ignored) {} + Socket client = serverSocket.accept(); + //отправляем клиенту его id + client.getOutputStream().write(lastClientId); + clientSockets.put(lastClientId, client); + MCServer.getClientSockets().put(lastClientId++, client); + new ServerReceiverThread(client).start(); + } catch (SocketTimeoutException e) { + + } catch (IOException e) { + throw new RuntimeException(e); + } } - return socketAddressList; + return clientSockets; } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/data/ProjectConfig.java b/src/main/java/ru/nsu/fit/dib/projectdib/data/ProjectConfig.java index 63b59d57..651e935e 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/data/ProjectConfig.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/data/ProjectConfig.java @@ -1,5 +1,7 @@ package ru.nsu.fit.dib.projectdib.data; +import javafx.scene.image.Image; + /** * Настройки игры, не изменяемые пользователем. */ @@ -20,6 +22,9 @@ public interface ProjectConfig { String _menuSelectedButton = "assets/UI/elements/menu_selected_button1k.png"; String _returnButton = "assets/UI/elements/return_button1k.png"; String _returnSelectedButton = "assets/UI/elements/return_selected_button1k.png"; + String _loadingAnimation = "assets/UI/elements/loadingAnimation.gif"; + String style = "assets/UI/elements/style.css"; + Integer SERVER_PORT = 8080; //Weapon String _smallWeapon = "assets/textures/SmallWeapon.png"; String _mediumWeapon = "assets/textures/MediumWeapon.png"; @@ -27,4 +32,8 @@ public interface ProjectConfig { //================================================================================================ String CONTROLS_PATH = "src/main/resources/config/controls.json"; int _WEAPON_COLUMNS =16; + Image _smallWeapon_img = new Image(_smallWeapon); + Image _mediumWeapon_img = new Image(_mediumWeapon); + Image _bigWeapon_img = new Image(_bigWeapon); + Integer MAX_PLAYERS = 4; } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/spawn/HeroJSON.java b/src/main/java/ru/nsu/fit/dib/projectdib/data/json/spawn/HeroJSON.java deleted file mode 100644 index 17451226..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/spawn/HeroJSON.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.nsu.fit.dib.projectdib.data.json.spawn; - -import ru.nsu.fit.dib.projectdib.entity.creatures.HeroesFactory.HeroType; - -public class HeroJSON { - - private Integer id; - private Integer seed; - private HeroType heroType; - - public HeroType getHeroType() { - return heroType; - } - - public Integer getId() { - return id; - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/spawn/WeaponJSON.java b/src/main/java/ru/nsu/fit/dib/projectdib/data/json/spawn/WeaponJSON.java deleted file mode 100644 index a6984356..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/spawn/WeaponJSON.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.nsu.fit.dib.projectdib.data.json.spawn; - -import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; - -public class WeaponJSON { - - - private Integer id; - private Weapons weapon; - private Integer seed; - - public Integer getId() { - return id; - } - - public Integer getSeed() { - return seed; - } - - public Weapons getWeapon() { - return weapon; - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/Action.java b/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/Action.java deleted file mode 100644 index b6ce3e10..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/Action.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.nsu.fit.dib.projectdib.data.json.update; - -/** - * Действие существа. action - тип действия objectOfAction - объект над которым - * совершается действие(null, если действие осуществляется не над каким либо объектом) - */ -public class Action { - - ActionType type; - Integer objectOfAction; - - public Action(ActionType type, Integer objectOfAction) { - this.type = type; - this.objectOfAction = objectOfAction; - } - - public ActionType getType() { - return type; - } - - public Integer getObjectOfAction() { - return objectOfAction; - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/ActionType.java b/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/ActionType.java deleted file mode 100644 index 3b1d0034..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/ActionType.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.nsu.fit.dib.projectdib.data.json.update; - -/** - * Типы отслеживаемых действий существ - */ -public enum ActionType { - THROW, - ATTACK, TAKE, -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/UpdatedCreatureJSON.java b/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/UpdatedCreatureJSON.java deleted file mode 100644 index a8bd2b6e..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/UpdatedCreatureJSON.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.nsu.fit.dib.projectdib.data.json.update; - -import static ru.nsu.fit.dib.projectdib.data.json.update.ActionType.ATTACK; - -import com.almasb.fxgl.entity.Entity; -import java.util.List; -import javafx.geometry.Point2D; -import ru.nsu.fit.dib.projectdib.entity.components.CreatureComponent; -import ru.nsu.fit.dib.projectdib.newMultiplayer.ClientState; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; - -/** - * JSON для обновления существа - * position - расположение в мире - * directionView - направление - * взгляда actions - действия, совершенные существом - */ -public class UpdatedCreatureJSON { - List actions; - private final Point2D position; - private final Point2D directionView; - - public UpdatedCreatureJSON(Point2D position, Point2D directionView, List actions) { - this.actions = actions; - this.position = position; - this.directionView = directionView; - } - - public void updateCreature(Entity creature){ - - Point2D movingVector = position.add(creature.getPosition().multiply(-1)); - if (movingVector.getX()>0) creature.getComponent(CreatureComponent.class).right(); - else if (movingVector.getX()<0) creature.getComponent(CreatureComponent.class).left(); - if (movingVector.getY()>0) creature.getComponent(CreatureComponent.class).down(); - else if (movingVector.getY()<0) creature.getComponent(CreatureComponent.class).up(); - - creature.getComponent(CreatureComponent.class).bindDirectionView(entity -> directionView); - - actions.forEach(action -> { - switch (action.getType()){ - case ATTACK -> creature.getComponent(CreatureComponent.class).attack(); - case TAKE -> creature.getComponent(CreatureComponent.class).takeWeapon(MCClient.getClientState().getIdHashTable().get(action.getObjectOfAction())); - case THROW -> creature.getComponent(CreatureComponent.class).throwWeapon(); - } - }); - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/UpdatedWeaponJSON.java b/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/UpdatedWeaponJSON.java deleted file mode 100644 index d55e3aa4..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/data/json/update/UpdatedWeaponJSON.java +++ /dev/null @@ -1,29 +0,0 @@ -package ru.nsu.fit.dib.projectdib.data.json.update; - -import com.almasb.fxgl.entity.Entity; -import javafx.geometry.Point2D; - -/** - * JSON для обновления оружия userID - индефикатор владельца оружия (null, если ничье) - * position - расположение оружия в мире (null, если есть владелец) rotation - поворот - * оружия(null, если есть владелец) - */ -public class UpdatedWeaponJSON { - - private final Integer userID; - private final Point2D position; - private final double rotation; - - public UpdatedWeaponJSON(Integer userID, Point2D position, double rotation) { - this.userID = userID; - this.position = position; - this.rotation = rotation; - } - - public void updateWeapon(Entity weapon) { - if (userID == null) { - weapon.setPosition(position); - weapon.setRotation(rotation); - } - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/CreatureComponent.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/CreatureComponent.java index 0a55ab01..d9136c09 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/CreatureComponent.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/CreatureComponent.java @@ -10,13 +10,11 @@ import com.almasb.fxgl.entity.Entity; import com.almasb.fxgl.entity.component.Component; import com.almasb.fxgl.entity.components.CollidableComponent; -import com.almasb.fxgl.input.UserAction; import com.almasb.fxgl.physics.PhysicsComponent; import com.almasb.fxgl.texture.AnimatedTexture; import com.almasb.fxgl.texture.AnimationChannel; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.function.Function; import javafx.geometry.Point2D; @@ -47,13 +45,13 @@ public class CreatureComponent extends Component implements Moving { private PhysicsComponent physics; private String currentWeapon; private boolean isMoving = false; - + private static final Image img = new Image(_player); + private Point2D newPosition = null; public CreatureComponent(Creature creature, Point2D localAnchor) { this.localAnchor = localAnchor; this.creature = creature; int creatureNumber = creature.getModule(JFXModule.class).getImageID(); //animation settings - Image img = new Image(_player); animationMovement = new AnimationChannel(img, _player_numberColumns, _player_width, _player_height, Duration.millis(600), 5 + creatureNumber * 13, 8 + creatureNumber * 13); @@ -104,6 +102,13 @@ public void onUpdate(double tpf) { } else { rotate(SIDE.LEFT); } + if (newPosition!=null) { + double l=newPosition.add(getEntity().getPosition().multiply(-1)).magnitude(); + if (l<4) + { + physics.setLinearVelocity(0,0); + } + } physics.setLinearVelocity(physics.getLinearVelocity().multiply(Math.pow(1000, (-1) * tpf))); } @@ -142,6 +147,14 @@ public void stop() { physics.setVelocityY(0); physics.setVelocityX(0); } + public void moveToPoint(Point2D position){ + newPosition=position; + move(position); + } + private void move(Point2D position){ + Point2D movingVector = position.add(entity.getPosition().multiply(-1)); + physics.setLinearVelocity(movingVector.normalize().multiply(getCreature().getSpeed())); + } //================================================================================================== public Point2D getDirectionView() { diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/DataComponent.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/DataComponent.java new file mode 100644 index 00000000..d345ce2b --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/DataComponent.java @@ -0,0 +1,80 @@ +package ru.nsu.fit.dib.projectdib.entity.components; + +import com.almasb.fxgl.entity.Entity; +import com.almasb.fxgl.entity.component.Component; +import javafx.geometry.Point2D; +import ru.nsu.fit.dib.projectdib.EntityType; +import ru.nsu.fit.dib.projectdib.entity.creatures.modules.CreatureWeaponModule; +import ru.nsu.fit.dib.projectdib.entity.weapons.enums.modules.TextureModule; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; + +public class DataComponent extends Component { + + private Point2D position; + private Point2D rotation; + + public EntityType getEntityType() { + return entityType; + } + + private EntityType entityType; + private Integer bindedEntity; + private Integer id; + private int ownerID=-1; + + public DataComponent(EntityType entityType, Integer ownerID, Integer id) { + if (ownerID!=null) this.ownerID = ownerID; + this.entityType = entityType; + rotation = new Point2D(0, 0); + this.id = id; + } + @Override + public void onUpdate(double tpf) { + switch (entityType) { + case WEAPON -> { + rotation = getEntity().getComponent(WeaponComponent.class).getRotation(); + } + case PLAYER -> { + rotation = getEntity().getComponent(HeroComponent.class).getDirectionView(); + position = getEntity().getPosition(); + WeaponComponent weaponComponent = getEntity().getComponent(HeroComponent.class).getCreature() + .getModule(CreatureWeaponModule.class).getActiveWeapon().getModule( + TextureModule.class).getComponent(); + if (weaponComponent != null) { + bindedEntity = weaponComponent.getEntity().getComponent(DataComponent.class) + .getId(); + } + + } + default -> { + throw new RuntimeException("Unexpected entity with type:" + entityType); + } + } + } + public Point2D getRotation() { + return rotation; + } + + public Integer getBindedEntity() { + return bindedEntity; + } + + public Integer getId() { + return id; + } + + public Point2D getPosition() { + return position; + } + + public boolean isClientEntity() { + return ownerID == MCClient.getClientId(); + } + public int getOwnerID() { + return ownerID; + } + + public boolean isValid() { + return position!=null && rotation != null; + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/HeroComponent.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/HeroComponent.java index c6b76c86..99f8748c 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/HeroComponent.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/HeroComponent.java @@ -42,6 +42,7 @@ public class HeroComponent extends CreatureComponent implements Moving { private final double scale = 0.07; AnimationChannel animationWaiting; AnimationChannel animationBack; + private static final Image img = new Image(_player); private LocalTimer shootTimer = newLocalTimer(); private boolean isMoving = false; @@ -49,7 +50,6 @@ public class HeroComponent extends CreatureComponent implements Moving { public HeroComponent(Creature hero, Point2D localAnchor) { super(hero,localAnchor); int heroNumber = creature.getModule(JFXModule.class).getImageID(); - Image img = new Image(_player); animationWaiting = new AnimationChannel(img, _player_numberColumns, _player_width, _player_height, Duration.millis(450), 2 + heroNumber * 13, 4 + heroNumber * 13); diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/WeaponComponent.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/WeaponComponent.java index a8f7e603..79f653ca 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/WeaponComponent.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/components/WeaponComponent.java @@ -8,6 +8,7 @@ import com.almasb.fxgl.entity.Entity; import com.almasb.fxgl.entity.component.Component; import javafx.geometry.Point2D; +import ru.nsu.fit.dib.projectdib.entity.creatures.modules.CreatureWeaponModule; import ru.nsu.fit.dib.projectdib.entity.creatures.modules.JFXModule; import ru.nsu.fit.dib.projectdib.entity.weapons.Weapon; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.modules.SquareDamageModule; @@ -21,6 +22,7 @@ public class WeaponComponent extends Component { Double imgRadius; Double angle; Point2D rotatedPoint; + Point2D rotation; Point2D lastVectorView = new Point2D(0, 0); public WeaponComponent(Weapon weapon) { @@ -46,10 +48,10 @@ public Weapon getWeapon() { @Override public void onUpdate(double tpf) { - if (weapon.getUser() != null) { + if (weapon.getUser() != null && weapon.getUser().getModule(JFXModule.class).getComponent().getEntity()!=null) { Point2D userPos = weapon.getUser().getModule(JFXModule.class).getComponent().getEntity().getPosition(); Point2D vectorView = weapon.getUser().getModule(JFXModule.class).getComponent().getDirectionView(); - Point2D rotation = FXGLMath.rotate(vectorView.normalize(), new Point2D(0, 0), angle); + rotation = FXGLMath.rotate(vectorView.normalize(), new Point2D(0, 0), angle); Point2D position = userPos.add(vectorView.normalize().multiply(imgRadius)); getEntity().rotateToVector(rotation); @@ -58,6 +60,17 @@ public void onUpdate(double tpf) { getEntity().setY(position.getY()); } } + public Point2D getRotation(){ + return rotation; + } + public boolean hasUser(){ + return weapon.getUser()!=null; + } + + public boolean isActive() { + if (getWeapon().getUser()==null) return false; + return (getWeapon().getUser().getModule(CreatureWeaponModule.class).getActiveWeapon()==getWeapon()); + } /* public void attack() { diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/Creature.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/Creature.java index c5c970be..8427a235 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/Creature.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/Creature.java @@ -8,6 +8,7 @@ import ru.nsu.fit.dib.projectdib.entity.creatures.modules.SpecsModule; import ru.nsu.fit.dib.projectdib.entity.creatures.modules.CreatureWeaponModule; import ru.nsu.fit.dib.projectdib.entity.creatures.modules.WeaponSkillsModule; +import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.DamageType; import ru.nsu.fit.dib.projectdib.entity.weapons.Weapon; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.WeaponType; @@ -109,8 +110,8 @@ public CreatureBuilder setSpecs(int hp, int strength, int agility, int durabilit return this; } - public CreatureBuilder setStartWeapon(Weapon weapon) { - CreatureWeaponModule module = new CreatureWeaponModule(weapon); + public CreatureBuilder setStartWeapon(Weapons weaponType) { + CreatureWeaponModule module = new CreatureWeaponModule(weaponType); modules.put(CreatureWeaponModule.class, module); return this; } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/EnemiesFactory.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/EnemiesFactory.java index 2348a8a8..4e13bbd2 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/EnemiesFactory.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/EnemiesFactory.java @@ -2,6 +2,7 @@ import ru.nsu.fit.dib.projectdib.RandomSystem; import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory; +import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.WeaponType; import java.util.ArrayList; @@ -16,7 +17,7 @@ public static Creature getEnemy(EnemyType enemyType){ .setSpecs(RandomSystem.d(10), specsList.get(0), specsList.get(4), specsList.get(1), specsList.get(2), specsList.get(5), specsList.get(3)) - .setStartWeapon(WeaponFactory.getWeapon(WeaponFactory.Weapons.Hand)) + .setStartWeapon(WeaponFactory.Weapons.Hand) .setSkill(WeaponType.melee, 5) .build(); case ZOMBIE -> new Creature.CreatureBuilder(CreatureRarity.special, "Zombie") @@ -24,7 +25,7 @@ public static Creature getEnemy(EnemyType enemyType){ .setSpecs(RandomSystem.d(5), specsList.get(2), specsList.get(3), specsList.get(1), specsList.get(4), specsList.get(5), specsList.get(5)) - .setStartWeapon(WeaponFactory.getWeapon(WeaponFactory.Weapons.Sword)) + .setStartWeapon(Weapons.Sword) .setSkill(WeaponType.shooting, 2) .build(); case SKELETON -> new Creature.CreatureBuilder(CreatureRarity.special, "Zombie") @@ -32,7 +33,7 @@ public static Creature getEnemy(EnemyType enemyType){ .setSpecs(RandomSystem.d(5), specsList.get(2), specsList.get(3), specsList.get(1), specsList.get(4), specsList.get(5), specsList.get(5)) - .setStartWeapon(WeaponFactory.getWeapon(WeaponFactory.Weapons.Bow)) + .setStartWeapon(WeaponFactory.Weapons.Bow) .setSkill(WeaponType.shooting, 3) .build(); default -> throw new NullPointerException("Undeclared enemy type"); diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/HeroesFactory.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/HeroesFactory.java index b9985f59..6bb7b953 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/HeroesFactory.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/HeroesFactory.java @@ -1,14 +1,17 @@ package ru.nsu.fit.dib.projectdib.entity.creatures; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import ru.nsu.fit.dib.projectdib.RandomSystem; -import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory; import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.WeaponType; public class HeroesFactory { - public static Creature newHero(HeroType heroType,Integer seed) { + + public static Creature newHero(HeroType heroType, Integer seed) { List specsList = RandomSystem.generateCreatureSpecs(seed); return switch (heroType) { case Elf -> new Creature.CreatureBuilder(CreatureRarity.mediocre, "GigaElf") @@ -17,7 +20,7 @@ public static Creature newHero(HeroType heroType,Integer seed) { RandomSystem.d(10), specsList.get(3), specsList.get(0), specsList.get(2), specsList.get(5), specsList.get(4), specsList.get(1)) - .setStartWeapon(WeaponFactory.getWeapon(Weapons.Bow)) + .setStartWeapon(Weapons.Bow) .setSkill(WeaponType.shooting, 2) .build(); case JonnyS -> new Creature.CreatureBuilder(CreatureRarity.masterful, "Jonny") @@ -26,7 +29,7 @@ public static Creature newHero(HeroType heroType,Integer seed) { RandomSystem.d(10), specsList.get(4), specsList.get(0), specsList.get(1), specsList.get(3), specsList.get(5), specsList.get(2)) - .setStartWeapon(WeaponFactory.getWeapon(Weapons.AK47)) + .setStartWeapon(Weapons.AK47) .setSkill(WeaponType.shooting, 2).build(); case Knight -> new Creature.CreatureBuilder(CreatureRarity.ordinary, "Knight") .setID(1) @@ -34,7 +37,7 @@ public static Creature newHero(HeroType heroType,Integer seed) { RandomSystem.d(10), specsList.get(1), specsList.get(2), specsList.get(0), specsList.get(5), specsList.get(4), specsList.get(3)) - .setStartWeapon(WeaponFactory.getWeapon(Weapons.Sword)) + .setStartWeapon(Weapons.Sword) .setSkill(WeaponType.melee, 2) .build(); case Wizard -> new Creature.CreatureBuilder(CreatureRarity.special, "Wizard") @@ -44,7 +47,7 @@ public static Creature newHero(HeroType heroType,Integer seed) { specsList.get(3), specsList.get(0), specsList.get(2), specsList.get(5), specsList.get(4), specsList.get(1) ) - .setStartWeapon(WeaponFactory.getWeapon(Weapons.Staff)) + .setStartWeapon(Weapons.Staff) .setSkill(WeaponType.magic, 2) .build(); default -> throw new NullPointerException("Undeclared hero type"); @@ -52,14 +55,28 @@ public static Creature newHero(HeroType heroType,Integer seed) { } public enum HeroType { - Elf(CreatureRarity.mediocre), - Knight(CreatureRarity.ordinary), - Wizard(CreatureRarity.special), - JonnyS(CreatureRarity.masterful); - final CreatureRarity creatureRarity; + Elf(CreatureRarity.mediocre, "elf"), + Knight(CreatureRarity.ordinary, "knight"), + Wizard(CreatureRarity.special, "wizard"), + JonnyS(CreatureRarity.masterful, "jonnys"); + private final CreatureRarity creatureRarity; + + public String getName() { + return name; + } + + private final String name; + private static final Map map = Arrays.stream(values()) + .collect( + Collectors.toMap(orderStatus -> orderStatus.name, orderStatus -> orderStatus)); - HeroType(CreatureRarity creatureRarity) { + HeroType(CreatureRarity creatureRarity, String name) { this.creatureRarity = creatureRarity; + this.name = name; + } + + public static HeroType getByName(String findingName) { + return map.get(findingName); } public static List getAll(CreatureRarity rarity) { @@ -75,6 +92,6 @@ public static List getAll(CreatureRarity rarity) { public CreatureRarity getCreatureRarity() { return creatureRarity; } - + } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/modules/CreatureWeaponModule.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/modules/CreatureWeaponModule.java index 58dba508..61e514f2 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/modules/CreatureWeaponModule.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/creatures/modules/CreatureWeaponModule.java @@ -12,14 +12,21 @@ public class CreatureWeaponModule extends CreatureModule{ private int weaponSize; private List weapons; - public CreatureWeaponModule(Weapon startWeapon){ + public Weapons getStartWeapon() { + return startWeapon; + } + + private Weapons startWeapon; + + public CreatureWeaponModule(Weapons startWeapon){ + this.startWeapon=startWeapon; this.activeWeapon = 0; this.weaponSize = 2; this.weapons = new ArrayList<>(); for (int i = 0; i < weaponSize; i++) { weapons.add(WeaponFactory.getWeapon(Weapons.Hand)); } - changeWeapon(startWeapon); + changeWeapon(WeaponFactory.getWeapon(startWeapon)); user=null; } private Creature user; diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/WeaponFactory.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/WeaponFactory.java index 394360a3..8c21b9fa 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/WeaponFactory.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/WeaponFactory.java @@ -1,5 +1,9 @@ package ru.nsu.fit.dib.projectdib.entity.weapons; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; +import ru.nsu.fit.dib.projectdib.entity.creatures.HeroesFactory.HeroType; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.DamageType; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.WeaponRarity; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.WeaponSize; @@ -50,11 +54,26 @@ public static Weapon getWeapon(Weapons weapon) { } public enum Weapons { - Hand, - Rapier, - Sword, - AK47, - Bow, - Staff + Hand("hand"), + Rapier("rapier"), + Sword("sword"), + AK47("ak47"), + Bow("bow"), + Staff("staff"); + private static final Map map = Arrays.stream(values()) + .collect( + Collectors.toMap(orderStatus -> orderStatus.name, orderStatus -> orderStatus)); + + public String getName() { + return name; + } + + private final String name; + Weapons(String name) { + this.name=name; + } + public static Weapons getByName(String weaponName){ + return map.get(weaponName); + } } } \ No newline at end of file diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/enums/modules/TextureModule.java b/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/enums/modules/TextureModule.java index 1000f1b4..06685a44 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/enums/modules/TextureModule.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/entity/weapons/enums/modules/TextureModule.java @@ -1,5 +1,6 @@ package ru.nsu.fit.dib.projectdib.entity.weapons.enums.modules; +import javafx.scene.image.Image; import ru.nsu.fit.dib.projectdib.data.ProjectConfig; import ru.nsu.fit.dib.projectdib.entity.components.WeaponComponent; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.WeaponSize; @@ -38,11 +39,11 @@ public int getWeaponID() { } - public String getTexturePath() { + public Image getTexturePath() { return switch (weaponSize) { - case SMALL -> ProjectConfig._smallWeapon; - case MEDIUM -> ProjectConfig._mediumWeapon; - case BIG -> ProjectConfig._bigWeapon; + case SMALL -> ProjectConfig._smallWeapon_img; + case MEDIUM -> ProjectConfig._mediumWeapon_img; + case BIG -> ProjectConfig._bigWeapon_img; }; } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/ActionStatus.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/ActionStatus.java new file mode 100644 index 00000000..ba1db659 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/ActionStatus.java @@ -0,0 +1,16 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +@SuppressWarnings("unused") +public final class ActionStatus { + private ActionStatus() { } + public static final byte CREATED = 0; + public static final byte APPROVED = 1; + public static final byte REFUSED = 2; + + public static final String[] names = { "CREATED", "APPROVED", "REFUSED", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/EntityStateData.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/EntityStateData.java new file mode 100644 index 00000000..3f238524 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/EntityStateData.java @@ -0,0 +1,41 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +import java.nio.*; +import java.lang.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class EntityStateData extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_8(); } + public static EntityStateData getRootAsEntityStateData(ByteBuffer _bb) { return getRootAsEntityStateData(_bb, new EntityStateData()); } + public static EntityStateData getRootAsEntityStateData(ByteBuffer _bb, EntityStateData obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public EntityStateData __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int id() { int o = __offset(4); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D pos() { return pos(new ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D()); } + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D pos(ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D obj) { int o = __offset(6); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D rot() { return rot(new ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D()); } + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D rot(ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D obj) { int o = __offset(8); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + public int activeWeapon() { int o = __offset(10); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + + public static void startEntityStateData(FlatBufferBuilder builder) { builder.startTable(4); } + public static void addId(FlatBufferBuilder builder, int id) { builder.addInt(0, id, 0); } + public static void addPos(FlatBufferBuilder builder, int posOffset) { builder.addStruct(1, posOffset, 0); } + public static void addRot(FlatBufferBuilder builder, int rotOffset) { builder.addStruct(2, rotOffset, 0); } + public static void addActiveWeapon(FlatBufferBuilder builder, int activeWeapon) { builder.addInt(3, activeWeapon, 0); } + public static int endEntityStateData(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public EntityStateData get(int j) { return get(new EntityStateData(), j); } + public EntityStateData get(EntityStateData obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/EntityStateDataList.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/EntityStateDataList.java new file mode 100644 index 00000000..2e18d87d --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/EntityStateDataList.java @@ -0,0 +1,118 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +import java.nio.*; +import java.lang.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class EntityStateDataList extends Table { + + public static void ValidateVersion() { + Constants.FLATBUFFERS_2_0_8(); + } + + public static EntityStateDataList getRootAsEntityStateDataList(ByteBuffer _bb) { + return getRootAsEntityStateDataList(_bb, new EntityStateDataList()); + } + + public static EntityStateDataList getRootAsEntityStateDataList(ByteBuffer _bb, + EntityStateDataList obj) { + _bb.order(ByteOrder.LITTLE_ENDIAN); + return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); + } + + public void __init(int _i, ByteBuffer _bb) { + __reset(_i, _bb); + } + + public EntityStateDataList __assign(int _i, ByteBuffer _bb) { + __init(_i, _bb); + return this; + } + + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData list(int j) { + return list(new ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData(), j); + } + + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData list( + ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData obj, int j) { + int o = __offset(4); + return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; + } + + public int listLength() { + int o = __offset(4); + return o != 0 ? __vector_len(o) : 0; + } + + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData.Vector listVector() { + return listVector( + new ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData.Vector()); + } + + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData.Vector listVector( + ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData.Vector obj) { + int o = __offset(4); + return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; + } + + public static int createEntityStateDataList(FlatBufferBuilder builder, + int listOffset) { + builder.startTable(1); + EntityStateDataList.addList(builder, listOffset); + return EntityStateDataList.endEntityStateDataList(builder); + } + + public static void startEntityStateDataList(FlatBufferBuilder builder) { + builder.startTable(1); + } + + public static void addList(FlatBufferBuilder builder, int listOffset) { + builder.addOffset(0, listOffset, 0); + } + + public static int createListVector(FlatBufferBuilder builder, int[] data) { + builder.startVector(4, data.length, 4); + for (int i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); + } + + public static void startListVector(FlatBufferBuilder builder, int numElems) { + builder.startVector(4, numElems, 4); + } + + public static int endEntityStateDataList(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + + public static void finishEntityStateDataListBuffer(FlatBufferBuilder builder, int offset) { + builder.finish(offset); + } + + public static void finishSizePrefixedEntityStateDataListBuffer(FlatBufferBuilder builder, + int offset) { + builder.finishSizePrefixed(offset); + } + + public static final class Vector extends BaseVector { + + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { + __reset(_vector, _element_size, _bb); + return this; + } + + public EntityStateDataList get(int j) { + return get(new EntityStateDataList(), j); + } + + public EntityStateDataList get(EntityStateDataList obj, int j) { + return obj.__assign(__indirect(__element(j), bb), bb); + } + } +} + diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/NewEntityData.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/NewEntityData.java new file mode 100644 index 00000000..27db558c --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/NewEntityData.java @@ -0,0 +1,52 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class NewEntityData extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_8(); } + public static NewEntityData getRootAsNewEntityData(ByteBuffer _bb) { return getRootAsNewEntityData(_bb, new NewEntityData()); } + public static NewEntityData getRootAsNewEntityData(ByteBuffer _bb, NewEntityData obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public NewEntityData __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public String type() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer typeAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } + public ByteBuffer typeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 1); } + public int seed() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData state() { return state(new ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData()); } + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData state(ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData obj) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + + public static int createNewEntityData(FlatBufferBuilder builder, + int typeOffset, + int seed, + int stateOffset) { + builder.startTable(3); + NewEntityData.addState(builder, stateOffset); + NewEntityData.addSeed(builder, seed); + NewEntityData.addType(builder, typeOffset); + return NewEntityData.endNewEntityData(builder); + } + + public static void startNewEntityData(FlatBufferBuilder builder) { builder.startTable(3); } + public static void addType(FlatBufferBuilder builder, int typeOffset) { builder.addOffset(0, typeOffset, 0); } + public static void addSeed(FlatBufferBuilder builder, int seed) { builder.addInt(1, seed, 0); } + public static void addState(FlatBufferBuilder builder, int stateOffset) { builder.addOffset(2, stateOffset, 0); } + public static int endNewEntityData(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public NewEntityData get(int j) { return get(new NewEntityData(), j); } + public NewEntityData get(NewEntityData obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/Point2D.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/Point2D.java new file mode 100644 index 00000000..f5129a8e --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/Point2D.java @@ -0,0 +1,31 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +import java.nio.*; +import java.lang.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Point2D extends Struct { + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public Point2D __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public double x() { return bb.getDouble(bb_pos + 0); } + public double y() { return bb.getDouble(bb_pos + 8); } + + public static int createPoint2D(FlatBufferBuilder builder, double x, double y) { + builder.prep(8, 16); + builder.putDouble(y); + builder.putDouble(x); + return builder.offset(); + } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public Point2D get(int j) { return get(new Point2D(), j); } + public Point2D get(Point2D obj, int j) { return obj.__assign(__element(j), bb); } + } +} + diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/SpawnActionData.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/SpawnActionData.java new file mode 100644 index 00000000..72a4b67d --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/generated/SpawnActionData.java @@ -0,0 +1,44 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class SpawnActionData extends Table { + public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_8(); } + public static SpawnActionData getRootAsSpawnActionData(ByteBuffer _bb) { return getRootAsSpawnActionData(_bb, new SpawnActionData()); } + public static SpawnActionData getRootAsSpawnActionData(ByteBuffer _bb, SpawnActionData obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public SpawnActionData __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.NewEntityData data() { return data(new ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.NewEntityData()); } + public ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.NewEntityData data(ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.NewEntityData obj) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + + public static int createSpawnActionData(FlatBufferBuilder builder, + int dataOffset) { + builder.startTable(1); + SpawnActionData.addData(builder, dataOffset); + return SpawnActionData.endSpawnActionData(builder); + } + + public static void startSpawnActionData(FlatBufferBuilder builder) { builder.startTable(1); } + public static void addData(FlatBufferBuilder builder, int dataOffset) { builder.addOffset(0, dataOffset, 0); } + public static int endSpawnActionData(FlatBufferBuilder builder) { + int o = builder.endTable(); + return o; + } + public static void finishSpawnActionDataBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset); } + public static void finishSizePrefixedSpawnActionDataBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset); } + + public static final class Vector extends BaseVector { + public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } + + public SpawnActionData get(int j) { return get(new SpawnActionData(), j); } + public SpawnActionData get(SpawnActionData obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } + } +} + diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/serialization/FBSDeserializer.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/serialization/FBSDeserializer.java new file mode 100644 index 00000000..c7fd2913 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/serialization/FBSDeserializer.java @@ -0,0 +1,49 @@ +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.serialization; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import javafx.geometry.Point2D; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateDataList; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.NewEntityData; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.SpawnActionData; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.NewEntity; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.SpawnAction; + +public class FBSDeserializer { + + public static List deserializeEntityStateList(ByteBuffer buffer) { + EntityStateDataList entityStateDataList = EntityStateDataList.getRootAsEntityStateDataList(buffer); + List list = new ArrayList<>(); + for (int i = 0; i < entityStateDataList.listLength(); i++) { + list.add(deserializeEntityState(entityStateDataList.list(i))); + } + return list; + } + + public static SpawnAction deserializeSpawnAction(ByteBuffer buffer) { + SpawnActionData spawnActionData = SpawnActionData.getRootAsSpawnActionData(buffer); + return new SpawnAction(deserializeNewEntity(spawnActionData.data())); + } + + private static NewEntity deserializeNewEntity(NewEntityData newEntityData) { + return new NewEntity(newEntityData.type(), + newEntityData.seed(), + deserializeEntityState(newEntityData.state())); + } + + private static EntityState deserializeEntityState(EntityStateData stateData) { + return new EntityState(stateData.id(), + deserializePoint2D(stateData.pos()), + deserializePoint2D(stateData.rot()), + stateData.activeWeapon()); + } + + private static Point2D deserializePoint2D( + ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D point) { + return new Point2D(point.x(), point.y()); + } + +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/serialization/FBSSerializer.java b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/serialization/FBSSerializer.java new file mode 100644 index 00000000..affec173 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/flatbuffersclasses/serialization/FBSSerializer.java @@ -0,0 +1,53 @@ +package ru.nsu.fit.dib.projectdib.flatbuffersclasses.serialization; + +import static ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.SpawnActionData.createSpawnActionData; + +import com.google.flatbuffers.FlatBufferBuilder; +import java.nio.ByteBuffer; +import java.util.List; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateData; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.EntityStateDataList; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.NewEntityData; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.generated.Point2D; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.NewEntity; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.SpawnAction; + +public class FBSSerializer { + + private static final int INITAL_SIZE = 1024; + + public static ByteBuffer serialize(List entityStateList) { + FlatBufferBuilder builder = new FlatBufferBuilder(INITAL_SIZE); + int[] list = new int[entityStateList.size()]; + for (int i = 0; i < entityStateList.size(); i++) { + EntityState state = entityStateList.get(i); + list[i] = createEntityStateData(builder,state); + } + int i = builder.createVectorOfTables(list); + int entityStateDataList = EntityStateDataList.createEntityStateDataList(builder,i); + builder.finish(entityStateDataList); + return builder.dataBuffer(); + } + public static ByteBuffer serialize(SpawnAction action){ + FlatBufferBuilder builder = new FlatBufferBuilder(INITAL_SIZE); + int spawnActionData = createSpawnActionData(builder, + createNewEntityData(builder, action.getNewEntity())); + builder.finish(spawnActionData); + return builder.dataBuffer(); + } + private static int createNewEntityData(FlatBufferBuilder builder, NewEntity newEntity){ + return NewEntityData.createNewEntityData(builder, + builder.createString(newEntity.getEntityType()), + newEntity.getSeed(), + createEntityStateData(builder,newEntity.getState())); + } + private static int createEntityStateData(FlatBufferBuilder builder, EntityState state) { + EntityStateData.startEntityStateData(builder); + EntityStateData.addId(builder, state.getId()); + EntityStateData.addPos(builder, Point2D.createPoint2D(builder,state.getPosition().getX(),state.getPosition().getY())); + EntityStateData.addRot(builder, Point2D.createPoint2D(builder,state.getRotation().getX(),state.getRotation().getY())); + EntityStateData.addActiveWeapon(builder, state.getActiveWeapon()); + return EntityStateData.endEntityStateData(builder); + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/init_app/InputListener.java b/src/main/java/ru/nsu/fit/dib/projectdib/init_app/InputListener.java deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/initapp/GameInitializer.java b/src/main/java/ru/nsu/fit/dib/projectdib/initapp/GameInitializer.java index 54eb19bb..28bdf792 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/initapp/GameInitializer.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/initapp/GameInitializer.java @@ -16,6 +16,7 @@ import ru.nsu.fit.dib.projectdib.Factory; import ru.nsu.fit.dib.projectdib.RandomSystem; import ru.nsu.fit.dib.projectdib.data.RandomCharacterSystem; +import ru.nsu.fit.dib.projectdib.entity.components.DataComponent; import ru.nsu.fit.dib.projectdib.entity.components.HeroComponent; import ru.nsu.fit.dib.projectdib.entity.creatures.HeroesFactory.HeroType; import ru.nsu.fit.dib.projectdib.entity.creatures.modules.CreatureWeaponModule; @@ -29,6 +30,8 @@ import ru.nsu.fit.dib.projectdib.environment.mapperobjects.WallMapper; import ru.nsu.fit.dib.projectdib.environment.tmxbuilder.LevelToTmx; import ru.nsu.fit.dib.projectdib.newMultiplayer.EntitySpawner; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.NewEntity; /** * Инициализатор игры. @@ -47,25 +50,23 @@ public void run() { factory = new Factory(); getGameWorld().addEntityFactory(factory); - Level lvl = new Level(new Random().nextInt(), 64, 64, 1, 15); + Level lvl = new Level(12345, 64, 64, 1, 15); String levelName = "levels/" + LevelToTmx.levelToTmx(lvl); LevelSetter.setLevelFromMap(levelName, getGameWorld()); WallMapper wallMapper = new WallMapper(2560, 160, lvl.map); //lvl.print() - + Entity weapon; double x = (lvl.start.getCentrePoint().x) * 160; double y = (lvl.start.getCentrePoint().y) * 160; Point2D position = new Point2D(x,y); - Pair pair = Factory.spawnHero(HeroType.Elf,position,true, RandomSystem.random.nextInt()); - player=pair.getKey(); - //Entity weapon = Factory.spawnWeapon(Weapons.Sword,position); try { - Entity s = EntitySpawner.spawn("weapon", position, "Sword", null).get(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { + System.out.println(HeroType.Elf.getName()); + player = EntitySpawner.spawn(new NewEntity(HeroType.Elf.getName(),123,position,null)).get(); + System.out.println(player.getComponent(HeroComponent.class).getCreature().getSpeed()); + } catch (ExecutionException | InterruptedException e) { throw new RuntimeException(e); } + System.out.println("e"); player.addComponent(new ChunkLoaderComponent(new ChunkLoader(wallMapper))); //=================================== //SpawnData sd2 = new SpawnData(x,y); diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/initapp/InputListener.java b/src/main/java/ru/nsu/fit/dib/projectdib/initapp/InputListener.java index b28facd3..5e888060 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/initapp/InputListener.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/initapp/InputListener.java @@ -7,26 +7,25 @@ import static com.almasb.fxgl.dsl.FXGL.onKey; import static com.almasb.fxgl.dsl.FXGL.onKeyUp; import static com.almasb.fxgl.dsl.FXGL.spawn; +import static ru.nsu.fit.dib.projectdib.newMultiplayer.EntitySpawner.doAction; import com.almasb.fxgl.entity.Entity; -import com.almasb.fxgl.entity.SpawnData; -import com.almasb.fxgl.entity.action.Action; import com.almasb.fxgl.entity.components.CollidableComponent; -import com.almasb.fxgl.entity.components.IDComponent; import com.almasb.fxgl.input.UserAction; import com.almasb.fxgl.input.virtual.VirtualButton; -import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import javafx.geometry.Point2D; import javafx.scene.input.KeyCode; import javafx.scene.input.MouseButton; +import javafx.util.Pair; import ru.nsu.fit.dib.projectdib.EntityType; import ru.nsu.fit.dib.projectdib.data.Controls; +import ru.nsu.fit.dib.projectdib.entity.components.DataComponent; import ru.nsu.fit.dib.projectdib.entity.components.HeroComponent; import ru.nsu.fit.dib.projectdib.entity.creatures.Creature; import ru.nsu.fit.dib.projectdib.entity.creatures.modules.CreatureWeaponModule; import ru.nsu.fit.dib.projectdib.entity.weapons.enums.modules.TextureModule; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.TakeWeaponAction; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.MessageType; /** * Инициализатор действий со входными данными (например, с клавиатуры) @@ -83,14 +82,19 @@ protected void onActionBegin() { protected void onActionBegin() { HeroComponent playerComponent = player.getComponent(HeroComponent.class); List list = playerComponent.findWeapon(); + //---------------------------------------- if (list.size() >= 1) { //Спрашиваем сервер можно ли забрать Weapon + // TODO: 17.04.2023 надо раскоммитить + //doAction(new Pair<>(MessageType.ACTION, new TakeWeaponAction(player.getComponent(DataComponent.class).getId(),list.get(0).getComponent(DataComponent.class).getId()))); + //player.getComponent(DataComponent.class).addAction(new Action(ActionType.TAKE,list.get(0).getComponent(DataComponent.class).getId())); //если да то: - playerComponent.takeWeapon(list.get(0)); + //playerComponent.takeWeapon(list.get(0)); } else { + //player.getComponent(DataComponent.class).addAction(new Action(ActionType.THROW,null)); //Если Weapon рядом нет то прашиваем можно ли выбрость: - playerComponent.throwWeapon(); + //playerComponent.throwWeapon(); } //Вообще эту часть нужно будет убрать тк действие будет совершаться из распакованного JSON-а //------------------------------------------ diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/ClientState.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/ClientState.java index 5e2d4e6d..4cb62363 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/ClientState.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/ClientState.java @@ -1,24 +1,21 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer; -import static com.almasb.fxgl.dsl.FXGLForKtKt.spawn; - -import com.almasb.fxgl.core.math.Vec2; import com.almasb.fxgl.entity.Entity; -import com.almasb.fxgl.entity.components.IDComponent; -import com.almasb.fxgl.physics.PhysicsComponent; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import javafx.geometry.Point2D; -import ru.nsu.fit.dib.projectdib.Factory; -import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; +import javafx.util.Pair; +import ru.nsu.fit.dib.projectdib.entity.components.DataComponent; +import ru.nsu.fit.dib.projectdib.entity.components.HeroComponent; +import ru.nsu.fit.dib.projectdib.entity.components.WeaponComponent; import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.NewEntity; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.GameAction; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.NewEntity; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.SpawnAction; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.MessageType; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.Utils; public class ClientState { @@ -29,40 +26,47 @@ public Map getIdHashTable() { //Хранятся все ID всех отслеживаемых Entity private final Map idHashTable = new ConcurrentHashMap<>(); - public List spawnEntities(List newEntities) { - if (newEntities.isEmpty()) { - return new ArrayList<>(); - } - List entityList = new ArrayList<>(); - for (int i = 0; i < newEntities.size(); i++) { - if (Objects.equals(newEntities.get(i).getName(), "weapon")) { - Entity entity = Factory.spawnWeapon(Weapons.valueOf(newEntities.get(i).getEntityType()), newEntities.get(i).getPosition()); - idHashTable.put(newEntities.get(i).getId(), entity); - entityList.add(entity); - } - } - return entityList; - } - public void updateEntities(List entityStates) { + Utils.delay(); entityStates.forEach(entityState -> { if (!idHashTable.containsKey(entityState.getId())) { // TODO: 14.03.2023 вызов метода отправки пакета ошибки + return; } - Entity entity = idHashTable.get(entityState.getId()); - Point2D currPos = entity.getPosition(); - Point2D newPos = entityState.getPosition(); - entity.setPosition(new Vec2(newPos)); + if (!MCClient.getClientState().getIdHashTable().get(entityState.getId()).hasComponent(DataComponent.class)){ + System.out.println("someone"); + return; + } + if (MCClient.getClientState().getIdHashTable().get(entityState.getId()).getComponent( + DataComponent.class).isClientEntity()) { + return; + } + entityState.update(); }); } - public List getEntityStates() { + public List getEntityStatesByOwnerId(Integer id) { return idHashTable.entrySet().stream() - .map(e -> new EntityState(e.getKey(), e.getValue().getPosition(), null, null)).collect( - Collectors.toList()); + .filter(e->e.getValue().hasComponent(DataComponent.class)) + .filter(e -> e.getValue().getComponent(DataComponent.class).getOwnerID() == id) + .filter(e -> e.getValue().getComponent(DataComponent.class).isValid()) + .map(e -> new EntityState(e.getKey(), + e.getValue().getComponent(DataComponent.class).getPosition(), + e.getValue().getComponent(DataComponent.class).getRotation(), + e.getValue().getComponent(DataComponent.class).getBindedEntity()) + ).collect(Collectors.toList()); } - public Entity acceptedSpawn(NewEntity newEntity) { - return MCClient.getClientThread().spawnNewEntity(newEntity); + acceptedAction(new Pair<>(MessageType.SPAWN, new SpawnAction(newEntity))); + Entity player = null; + // TODO: 19.04.2023 Observer pattern + while (player == null) { + player = idHashTable.get(newEntity.getID()); + } + return player; + } + + public void acceptedAction(Pair action) { + MCClient.getClientSenderThread().addActionTask(action); } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/EntitySpawner.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/EntitySpawner.java index d0a49667..8cfd34e7 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/EntitySpawner.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/EntitySpawner.java @@ -1,13 +1,13 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer; import com.almasb.fxgl.entity.Entity; -import com.almasb.fxgl.entity.SpawnData; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; -import javafx.application.Platform; -import javafx.geometry.Point2D; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.NewEntity; +import javafx.util.Pair; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.GameAction; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.NewEntity; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.MessageType; public final class EntitySpawner { @@ -15,21 +15,10 @@ private EntitySpawner() { throw new UnsupportedOperationException(); } - public static Future spawn(String entityName, Point2D position, String entityType, - Integer seed) { - NewEntity newEntity = new NewEntity(null, entityName, position, entityType, seed); - return CompletableFuture.supplyAsync(() -> { - final Entity[] entity = {null}; - Thread compThread = Thread.currentThread(); - Platform.runLater(() -> { - entity[0] = MCClient.getClientState().acceptedSpawn(newEntity); - compThread.interrupt(); - }); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } - return entity[0]; - }); + public static Future spawn(NewEntity newEntity) { + return CompletableFuture.supplyAsync(() -> MCClient.getClientState().acceptedSpawn(newEntity)); + } + public static void doAction(Pair action) { + CompletableFuture.runAsync(() -> MCClient.getClientState().acceptedAction(action)); } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ClientConfig.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ClientConfig.java index a5746d1f..474a271f 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ClientConfig.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ClientConfig.java @@ -1,17 +1,11 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.config; -import com.almasb.fxgl.entity.SpawnData; -import com.google.gson.GsonBuilder; -import java.net.DatagramSocket; -import java.net.SocketAddress; -import java.net.SocketException; -import ru.nsu.fit.dib.projectdib.entity.weapons.Weapon; +import java.net.Socket; import ru.nsu.fit.dib.projectdib.newMultiplayer.ClientState; -import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientThread; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientReceiverThread; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientSenderThread; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.EMCClient; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; public final class ClientConfig { @@ -20,29 +14,26 @@ private ClientConfig() { } public static void init() { - MCClient.addBean(EMCClient.GSON, new GsonBuilder().serializeNulls() - .create()); - addClientSocket(); - MCClient.addBean(EMCClient.SENDER, new Sender(MCClient.getClientSocket(), MCClient.getGson())); - MCClient.addBean(EMCClient.RECEIVER, new Receiver(MCClient.getClientSocket(), MCClient.getGson())); MCClient.addBean(EMCClient.CLIENT_STATE, new ClientState()); + addClientSenderThread(new ClientSenderThread()); + addClientReceiverThread(new ClientReceiverThread()); } - private static void addClientSocket() { - DatagramSocket datagramSocket; - try { - datagramSocket = new DatagramSocket(9090); - } catch (SocketException e) { - throw new RuntimeException(e); - } - MCClient.addBean(EMCClient.CLIENT_SOCKET, datagramSocket); + public static void addClientId(Integer id) { + MCClient.addBean(EMCClient.CLIENT_ID, id); } - public static void addServerAddress(SocketAddress socketAddress) { - MCClient.addBean(EMCClient.SERVER_ADDRESS, socketAddress); + public static void addClientSenderThread(ClientSenderThread thread) { + thread.start(); + MCClient.addBean(EMCClient.CLIENT_SENDER_THREAD, thread); } - public static void addClientThread(ClientThread thread) { - MCClient.addBean(EMCClient.CLIENT_THREAD, thread); + public static void addClientReceiverThread(ClientReceiverThread thread) { + thread.start(); + MCClient.addBean(EMCClient.CLIENT_RECEIVER_THREAD, thread); + } + + public static void addClientSocket(Socket socket) { + MCClient.addBean(EMCClient.CLIENT_SOCKET, socket); } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ServerConfig.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ServerConfig.java index f96436f1..02bc6d2f 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ServerConfig.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/config/ServerConfig.java @@ -1,18 +1,13 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.config; -import com.almasb.fxgl.entity.SpawnData; -import com.google.gson.GsonBuilder; -import java.net.DatagramSocket; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.List; -import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ServerThread; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ServerActionThread; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.EMCServer; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.MCServer; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ServerUpdaterThread; public final class ServerConfig { @@ -21,29 +16,22 @@ private ServerConfig() { } public static void init() { - MCServer.addBean(EMCServer.GSON, new GsonBuilder().serializeNulls() - .create()); - addServerSocket(); - - MCServer.addBean(EMCServer.SENDER, new Sender(MCServer.getServerSocket(), MCServer.getGson())); - MCServer.addBean(EMCServer.RECEIVER, new Receiver(MCServer.getServerSocket(), MCServer.getGson())); + addServerActionThread(new ServerActionThread()); + addServerUpdaterThread(new ServerUpdaterThread()); + addClientSockets(new ConcurrentHashMap<>()); } - private static void addServerSocket() { - DatagramSocket datagramSocket; - try { - datagramSocket = new DatagramSocket(8080); - } catch (SocketException e) { - throw new RuntimeException(e); - } - MCServer.addBean(EMCServer.SERVER_SOCKET, datagramSocket); + public static void addClientSockets(Map sockets) { + MCServer.addBean(EMCServer.CLIENT_SOCKETS, sockets); } - public static void addClientAddresses(List socketAddresses) { - MCServer.addBean(EMCServer.CLIENT_ADDRESSES, socketAddresses); + public static void addServerActionThread(ServerActionThread thread) { + thread.start(); + MCServer.addBean(EMCServer.SERVER_ACTION_THREAD, thread); } - public static void addServerThread(ServerThread thread) { - MCServer.addBean(EMCServer.SERVER_THREAD, thread); + public static void addServerUpdaterThread(ServerUpdaterThread thread) { + thread.start(); + MCServer.addBean(EMCServer.SERVER_UPDATER_THREAD, thread); } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/EMCClient.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/EMCClient.java index c2826617..7016f623 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/EMCClient.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/EMCClient.java @@ -2,11 +2,9 @@ public enum EMCClient { + CLIENT_ID, CLIENT_SOCKET, - CLIENT_THREAD, - SERVER_ADDRESS, - SENDER, - RECEIVER, - CLIENT_STATE, - GSON + CLIENT_SENDER_THREAD, + CLIENT_RECEIVER_THREAD, + CLIENT_STATE } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/MCClient.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/MCClient.java index 6f5a11ca..246e56a5 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/MCClient.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/client/MCClient.java @@ -1,11 +1,10 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.context.client; -import com.google.gson.Gson; -import java.net.DatagramSocket; -import java.net.SocketAddress; +import java.net.Socket; import java.util.HashMap; import ru.nsu.fit.dib.projectdib.newMultiplayer.ClientState; -import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientThread; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientReceiverThread; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientSenderThread; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.ContextException; import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; @@ -25,41 +24,33 @@ public static void addBean(EMCClient emcClient, Object bean) { context.put(emcClient, bean); } - public static DatagramSocket getClientSocket() { - if (context.get(EMCClient.CLIENT_SOCKET) instanceof DatagramSocket s) { - return s; - } else { - throw new ContextException(); - } - } - - public static ClientThread getClientThread() { - if (context.get(EMCClient.CLIENT_THREAD) instanceof ClientThread t) { - return t; + public static Integer getClientId() { + if (context.get(EMCClient.CLIENT_ID) instanceof Integer i) { + return i; } else { throw new ContextException(); } } - public static SocketAddress getServerAddress() { - if (context.get(EMCClient.SERVER_ADDRESS) instanceof SocketAddress s) { + public static Socket getClientSocket() { + if (context.get(EMCClient.CLIENT_SOCKET) instanceof Socket s) { return s; } else { throw new ContextException(); } } - public static Sender getSender() { - if (context.get(EMCClient.SENDER) instanceof Sender s) { - return s; + public static ClientSenderThread getClientSenderThread() { + if (context.get(EMCClient.CLIENT_SENDER_THREAD) instanceof ClientSenderThread t) { + return t; } else { throw new ContextException(); } } - public static Receiver getReceiver() { - if (context.get(EMCClient.RECEIVER) instanceof Receiver r) { - return r; + public static ClientReceiverThread getClientReceiverThread() { + if (context.get(EMCClient.CLIENT_RECEIVER_THREAD) instanceof ClientReceiverThread t) { + return t; } else { throw new ContextException(); } @@ -72,12 +63,4 @@ public static ClientState getClientState() { throw new ContextException(); } } - - public static Gson getGson() { - if (context.get(EMCClient.GSON) instanceof Gson gson) { - return gson; - } else { - throw new ContextException(); - } - } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/EMCServer.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/EMCServer.java index 4656b5fc..8a3b9fbc 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/EMCServer.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/EMCServer.java @@ -2,10 +2,7 @@ public enum EMCServer { - SERVER_SOCKET, - SERVER_THREAD, - CLIENT_ADDRESSES, - RECEIVER, - SENDER, - GSON + SERVER_ACTION_THREAD, + SERVER_UPDATER_THREAD, + CLIENT_SOCKETS, } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/MCServer.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/MCServer.java index b04c3436..87baaf1d 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/MCServer.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/context/server/MCServer.java @@ -1,15 +1,14 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.context.server; -import com.google.gson.Gson; -import java.net.DatagramSocket; -import java.net.SocketAddress; +import java.net.Socket; import java.util.HashMap; import java.util.List; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.EMCClient; -import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ClientThread; +import java.util.Map; import ru.nsu.fit.dib.projectdib.newMultiplayer.context.ContextException; import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ServerActionThread; +import ru.nsu.fit.dib.projectdib.newMultiplayer.threads.ServerUpdaterThread; public final class MCServer { @@ -24,49 +23,27 @@ public static void addBean(EMCServer emcServer, Object bean) { context.put(emcServer, bean); } - public static DatagramSocket getServerSocket() { - if (context.get(EMCServer.SERVER_SOCKET) instanceof DatagramSocket s) { - return s; - } else { - throw new ContextException(); - } - } - - public static ClientThread getClientThread() { - if (context.get(EMCServer.SERVER_THREAD) instanceof ClientThread t) { - return t; - } else { - throw new ContextException(); - } - } - public static List getClientAddresses() { - if (context.get(EMCServer.CLIENT_ADDRESSES) instanceof List l) { - return (List) l; - } else { - throw new ContextException(); - } - } - public static Sender getSender() { - if (context.get(EMCServer.SENDER) instanceof Sender s) { - return s; + public static Map getClientSockets() { + if (context.get(EMCServer.CLIENT_SOCKETS) instanceof Map l) { + return (Map) l; } else { throw new ContextException(); } } - public static Receiver getReceiver() { - if (context.get(EMCServer.RECEIVER) instanceof Receiver r) { - return r; + public static ServerActionThread getActionThread() { + if (context.get(EMCServer.SERVER_ACTION_THREAD) instanceof ServerActionThread t) { + return t; } else { throw new ContextException(); } } - public static Gson getGson() { - if (context.get(EMCServer.GSON) instanceof Gson gson) { - return gson; + public static ServerUpdaterThread getUpdaterThread() { + if (context.get(EMCServer.SERVER_UPDATER_THREAD) instanceof ServerUpdaterThread t) { + return t; } else { throw new ContextException(); } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/EntityState.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/EntityState.java index 4f5067e3..fe9f0396 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/EntityState.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/EntityState.java @@ -1,16 +1,33 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.data; -import java.util.List; +import com.almasb.fxgl.entity.Entity; +import java.util.Map; +import java.util.Objects; import javafx.geometry.Point2D; -import ru.nsu.fit.dib.projectdib.data.json.update.Action; +import org.jetbrains.annotations.NotNull; +import ru.nsu.fit.dib.projectdib.entity.components.DataComponent; +import ru.nsu.fit.dib.projectdib.entity.components.HeroComponent; +import ru.nsu.fit.dib.projectdib.entity.components.WeaponComponent; +import ru.nsu.fit.dib.projectdib.entity.creatures.modules.CreatureWeaponModule; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; public class EntityState { - private final Integer id; + + private final int id; private Point2D position; - private Point2D directionView; //для player - private List actions; //для player + private Point2D rotation; + private int bindedEntity=-1; //для player - активное оружие + + public EntityState(int id, @NotNull Point2D position, @NotNull Point2D rotation, Integer bindedEntity) { + this.id = id; + this.position = position; + this.rotation = rotation; + if (bindedEntity!=null) { + this.bindedEntity = bindedEntity; + } + } - public Integer getId() { + public int getId() { return id; } @@ -18,20 +35,62 @@ public Point2D getPosition() { return position; } - public Point2D getDirectionView() { - return directionView; - } - - public void setPosition(Point2D newCoordinate){ + public void setPosition(Point2D newCoordinate) { this.position = newCoordinate; } - public void setDirectionView(Point2D newAngle){ - this.directionView = newAngle; + + public Point2D getRotation() { + return rotation; } - public EntityState(Integer id, Point2D position, Point2D directionView, List actions){ - this.id=id; - this.position = position; - this.directionView = directionView; - this.actions = actions; + + public void setRotation(Point2D newAngle) { + this.rotation = newAngle; + } + + public void update() { + if (Objects.equals(id, MCClient.getClientId())) return; + + Map hashTable = MCClient.getClientState().getIdHashTable(); + Entity entity = hashTable.get(id); + if (entity==null) return; + // TODO: 12.04.2023 тут свич надо дописать + // TODO: 21.04.2023 иногда выскакивает DataComponent not found + switch (entity.getComponent(DataComponent.class).getEntityType()) { + case PLAYER -> { + if (position != null) { + // TODO: 21.04.2023 проверка HeroComponent + entity.getComponent(HeroComponent.class).moveToPoint(position); + } + entity.getComponent(HeroComponent.class).bindDirectionView(e -> rotation); + + CreatureWeaponModule module = entity.getComponent(HeroComponent.class).getCreature() + .getModule(CreatureWeaponModule.class); + + Entity weapon = MCClient.getClientState().getIdHashTable().get(bindedEntity); + if (weapon!=null && !weapon.getComponent(WeaponComponent.class).isActive()) { + module.getNextWeapon(); + } + + + } + } + } + + public int getActiveWeapon() { + return bindedEntity; + } + + public void setActiveWeapon(Integer weaponId) { + this.bindedEntity=weaponId; + } + + @Override + public String toString() { + return "EntityState{" + + "id=" + id + + ", position=" + position + + ", rotation=" + rotation + + ", bindedEntity=" + bindedEntity + + '}'; } -} +} \ No newline at end of file diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/GameStatePacket.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/GameStatePacket.java deleted file mode 100644 index 44a08ede..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/GameStatePacket.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.nsu.fit.dib.projectdib.newMultiplayer.data; - - -import java.util.List; - -public class GameStatePacket { - - private final List newEntityList; - private final List allCoordinatesOfEntitiesList; - - public List getNewEntityList() { - return newEntityList; - } - - public List getAllCoordinatesOfEntitiesList() { - return allCoordinatesOfEntitiesList; - } - - public GameStatePacket(List newEntityList, - List allCoordinatesOfEntitiesList) { - this.newEntityList = newEntityList; - this.allCoordinatesOfEntitiesList = allCoordinatesOfEntitiesList; - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/NewEntity.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/NewEntity.java deleted file mode 100644 index 2bbbd436..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/NewEntity.java +++ /dev/null @@ -1,40 +0,0 @@ -package ru.nsu.fit.dib.projectdib.newMultiplayer.data; - -import javafx.geometry.Point2D; - -public class NewEntity { - - private Integer id; - private final String name; - private Point2D position; - private String entityType; //HeroType, WeaponType, EnemyType - private Integer seed; //сид для генерации игрока - - public Integer getId() { - return id; - } - - public String getName() { - return name; - } - - public String getEntityType() { - return entityType; - } - - public Point2D getPosition() { - return position; - } - - public void setId(Integer id) { - this.id = id; - } - - public NewEntity(Integer id, String name, Point2D position, String entityType, Integer seed) { - this.id = id; - this.name = name; - this.position = position; - this.entityType = entityType; - this.seed = seed; - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/TypeAction.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/TypeAction.java new file mode 100644 index 00000000..61b64df3 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/TypeAction.java @@ -0,0 +1,10 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.data; + +public enum TypeAction { + SPAWN_HERO, + SPAWN, + TAKE, + THROW, + ATTACK, + +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/GameAction.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/GameAction.java new file mode 100644 index 00000000..63f7b57d --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/GameAction.java @@ -0,0 +1,7 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions; + + +public abstract class GameAction { + + public abstract void run(); +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/NewEntity.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/NewEntity.java new file mode 100644 index 00000000..a7556d89 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/NewEntity.java @@ -0,0 +1,73 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions; + +import com.almasb.fxgl.entity.Entity; +import java.util.Objects; +import javafx.geometry.Point2D; +import org.jetbrains.annotations.NotNull; +import ru.nsu.fit.dib.projectdib.Factory; +import ru.nsu.fit.dib.projectdib.entity.creatures.HeroesFactory.HeroType; +import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; + +public class NewEntity { + + private static final int DEFAULT_SEED = 1; + + private EntityState state; + + public String getEntityType() { + return entityType; + } + + private final String entityType; + private final int seed; + + public NewEntity(String entityType, Integer seed, @NotNull Point2D position,Integer weaponId) { + this.entityType = entityType; + this.seed = Objects.requireNonNullElse(seed, DEFAULT_SEED); + state = new EntityState(MCClient.getClientId(),position,new Point2D(0,0),weaponId); + } + public NewEntity(String entityType, Integer seed, EntityState state) { + this.entityType = entityType; + this.seed = Objects.requireNonNullElse(seed, DEFAULT_SEED); + this.state = state; + } + + public Entity spawn() { + HeroType hero=HeroType.getByName(entityType); + if (hero!=null) { + Entity heroEntity = Factory.spawnHero(hero, state.getPosition(), Objects.equals(state.getId(), MCClient.getClientId()), state.getId(), seed); + Entity weaponEntity = Factory.spawnStandardWeapon(state.getActiveWeapon(), state.getId(),heroEntity); + MCClient.getClientState().getIdHashTable().put(state.getActiveWeapon(), weaponEntity); + MCClient.getClientState().getIdHashTable().put(state.getId(), heroEntity); + return heroEntity; + } + Weapons weapon = Weapons.getByName(entityType); + if (weapon!=null) { + Entity weaponEntity = Factory.spawnWeapon(weapon, state.getPosition(), state.getId()); + MCClient.getClientState().getIdHashTable().put(state.getId(), weaponEntity); + return weaponEntity; + } + throw new IllegalArgumentException("Entity type not found"); + } + public void setWeaponId(Integer weaponId) { + state.setActiveWeapon(weaponId); + } + + public Integer getID() { + return state.getId(); + } + + public Integer getWeaponId() { + return state.getActiveWeapon(); + } + + public int getSeed() { + return seed; + } + + public EntityState getState() { + return state; + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/SpawnAction.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/SpawnAction.java new file mode 100644 index 00000000..6f9dafab --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/SpawnAction.java @@ -0,0 +1,20 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions; + +import javafx.application.Platform; + +public class SpawnAction extends GameAction { + + public NewEntity getNewEntity() { + return newEntity; + } + + private final NewEntity newEntity; + + public SpawnAction(NewEntity newEntity){ + this.newEntity=newEntity; + } + @Override + public void run() { + Platform.runLater(newEntity::spawn); + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/TakeWeaponAction.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/TakeWeaponAction.java new file mode 100644 index 00000000..5ad5ee32 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/TakeWeaponAction.java @@ -0,0 +1,28 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions; + +import com.almasb.fxgl.entity.Entity; +import ru.nsu.fit.dib.projectdib.entity.components.HeroComponent; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; + +public class TakeWeaponAction extends GameAction{ + private final Integer heroId; + + public Integer getWeaponId() { + return weaponId; + } + + private final Integer weaponId; + public TakeWeaponAction(Integer heroId,Integer weaponId){ + super(); + this.heroId=heroId; + this.weaponId=weaponId; + } + @Override + public void run() { + Entity hero = MCClient.getClientState().getIdHashTable().get(heroId); + if (hero==null) throw new IllegalArgumentException("Hero with id "+heroId+" not found"); + Entity weapon = MCClient.getClientState().getIdHashTable().get(weaponId); + if (weapon==null) throw new IllegalArgumentException("Weapon with id "+weaponId+" not found"); + hero.getComponent(HeroComponent.class).takeWeapon(weapon); + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/ThrowWeaponAction.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/ThrowWeaponAction.java new file mode 100644 index 00000000..226f7901 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/data/actions/ThrowWeaponAction.java @@ -0,0 +1,19 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions; + +import com.almasb.fxgl.entity.Entity; +import ru.nsu.fit.dib.projectdib.entity.components.HeroComponent; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; + +public class ThrowWeaponAction extends GameAction{ + private final Integer heroId; + public ThrowWeaponAction(Integer heroId){ + super(); + this.heroId=heroId; + } + @Override + public void run() { + Entity hero = MCClient.getClientState().getIdHashTable().get(heroId); + if (hero==null) throw new IllegalArgumentException("Hero with id "+heroId+" not found"); + hero.getComponent(HeroComponent.class).throwWeapon(); + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/exeptions/PacketTypeException.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/exeptions/PacketTypeException.java deleted file mode 100644 index ef457ad5..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/exeptions/PacketTypeException.java +++ /dev/null @@ -1,17 +0,0 @@ -package ru.nsu.fit.dib.projectdib.newMultiplayer.exeptions; - -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.GameStatePacket; - -public class PacketTypeException extends Exception { - - private final GameStatePacket gameStatePacket; - - - public PacketTypeException(GameStatePacket gameStatePacket) { - this.gameStatePacket = gameStatePacket; - } - - public GameStatePacket getGameStatePacket() { - return gameStatePacket; - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/MessageType.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/MessageType.java index 3cd60f0f..707fb46d 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/MessageType.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/MessageType.java @@ -1,16 +1,28 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.socket; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + public enum MessageType { ERROR((byte) 0), - NEW_STATE((byte) 1), - MAP((byte) 2); + UPDATE((byte) 1), + SPAWN((byte) 2), + ACTION((byte) 3), + MAP((byte) 4); private final byte id; + private static final Map map = Arrays.stream(MessageType.values()) + .collect(Collectors.toMap(messageType -> messageType.id, orderStatus -> orderStatus)); MessageType(byte id) { this.id = id; } + public static MessageType getMessageType(byte id) { + return map.get(id); + } + public byte getId() { return id; } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Receiver.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Receiver.java index 05c0a6fa..0512ba15 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Receiver.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Receiver.java @@ -1,45 +1,53 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.socket; -import com.google.gson.Gson; +import java.io.DataInputStream; import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.nio.charset.StandardCharsets; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.GameStatePacket; -import ru.nsu.fit.dib.projectdib.newMultiplayer.exeptions.PacketTypeException; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.util.Arrays; +import javafx.util.Pair; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.serialization.FBSDeserializer; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.SpawnAction; public class Receiver { - private final DatagramSocket socket; + private final Socket socket; - private final Gson gson; - - public Receiver(DatagramSocket socket, Gson gson) { + public Receiver(Socket socket) { this.socket = socket; - this.gson = gson; } - public GameStatePacket receive() throws PacketTypeException, SocketTimeoutException { - try { - socket.setSoTimeout(10000); - } catch (SocketException e) { - throw new RuntimeException(e); - } - byte[] byteArray = new byte[60000]; - DatagramPacket p = new DatagramPacket(byteArray, byteArray.length); + public Socket getSocket() { + return socket; + } + + public Pair receive() { + byte[] byteArray; + //Получаем что то try { - socket.receive(p); + DataInputStream dis = new DataInputStream(socket.getInputStream()); + int len = dis.readInt(); + byteArray = new byte[len]; + dis.readFully(byteArray); } catch (IOException e) { throw new RuntimeException(e); } - if (p.getData()[0] != MessageType.NEW_STATE.getId()) { - String json = new String(p.getData(), 1, p.getLength() - 1, StandardCharsets.UTF_8); - throw new PacketTypeException(gson.fromJson(json, GameStatePacket.class)); + //Передаем в буфер + byte[] data = new byte[byteArray.length - 1]; + System.arraycopy(byteArray, 1, data, 0, data.length); + ByteBuffer byteBuffer = ByteBuffer.allocate(data.length); + byteBuffer.put(data).flip(); + //System.out.println(MessageType.getMessageType(byteArray[0]).toString()+" received"); + switch (MessageType.getMessageType(byteArray[0])){ + case UPDATE -> { + return new Pair<>(MessageType.UPDATE, FBSDeserializer.deserializeEntityStateList(byteBuffer)); + } + case SPAWN -> { + return new Pair<>(MessageType.SPAWN, FBSDeserializer.deserializeSpawnAction(byteBuffer)); + } + default -> { + throw new IllegalArgumentException("Illegal packet type"); + } } - String json = new String(p.getData(), 1, p.getLength() - 1, StandardCharsets.UTF_8); - return gson.fromJson(json, GameStatePacket.class); } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Sender.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Sender.java index 492f30c4..1171ce2b 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Sender.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/socket/Sender.java @@ -1,60 +1,41 @@ package ru.nsu.fit.dib.projectdib.newMultiplayer.socket; -import com.google.gson.Gson; +import java.io.DataOutputStream; import java.io.IOException; -import java.io.StringWriter; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.GameStatePacket; -import ru.nsu.fit.dib.projectdib.newMultiplayer.exeptions.PacketSizeException; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; +import javafx.util.Pair; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.serialization.FBSSerializer; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.SpawnAction; public class Sender { - private final DatagramSocket socket; + public void send(Socket address, Pair message) { + ByteBuffer buffer = switch (message.getKey()){ + case SPAWN-> FBSSerializer.serialize((SpawnAction) message.getValue()); + case UPDATE -> FBSSerializer.serialize((List) message.getValue()); + default -> throw new IllegalArgumentException("Illegal type of message"); + }; - private final Gson gson; - - public Sender(DatagramSocket socket, Gson gson) { - this.socket = socket; - this.gson = gson; - } - - public void send(SocketAddress address, GameStatePacket gameStatePacket) { - StringWriter writer = new StringWriter(); - new Gson().toJson(gameStatePacket, GameStatePacket.class, writer); - byte[] byteArray = writer.toString().getBytes(StandardCharsets.UTF_8); - byte[] p = new byte[byteArray.length + 1]; - if (p.length > 55000) { - throw new PacketSizeException(); - } - p[0] = MessageType.NEW_STATE.getId(); - System.arraycopy(byteArray, 0, p, 1, byteArray.length); - DatagramPacket packet = new DatagramPacket(p, p.length, address); + //System.out.println(message.getKey().toString()+" sended"); + buffer.compact().position(0); + byte[] data = new byte[buffer.remaining()]; + buffer.get(data); + byte[] pt = new byte[data.length + 1]; + System.arraycopy(data, 0, pt, 1, data.length); + pt[0] = message.getKey().getId(); try { - socket.send(packet); + synchronized (address) { + DataOutputStream d = new DataOutputStream(address.getOutputStream()); + d.writeInt(pt.length); + address.getOutputStream().write(pt); + } } catch (IOException e) { throw new RuntimeException(e); } } - public void sendException(SocketAddress address, GameStatePacket gameStatePacket) { - StringWriter writer = new StringWriter(); - gson.toJson(gameStatePacket, GameStatePacket.class, writer); - byte[] byteArray = writer.toString().getBytes(StandardCharsets.UTF_8); - byte[] p = new byte[byteArray.length + 1]; - if (p.length > 55000) { - throw new PacketSizeException(); - } - p[0] = MessageType.ERROR.getId(); - System.arraycopy(byteArray, 0, p, 1, byteArray.length); - DatagramPacket packet = new DatagramPacket(p, p.length, address); - try { - socket.send(packet); - } catch (IOException e) { - throw new RuntimeException(e); - } - } } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientReceiverThread.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientReceiverThread.java new file mode 100644 index 00000000..51285c2c --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientReceiverThread.java @@ -0,0 +1,28 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; + +import java.util.List; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.GameAction; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; + +public class ClientReceiverThread extends Thread { + + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + Receiver receiver = new Receiver(MCClient.getClientSocket()); + var inPacket = receiver.receive(); + switch (inPacket.getKey()) { + case UPDATE -> { + MCClient.getClientState().updateEntities((List) inPacket.getValue()); + } + default -> { + GameAction gameAction = (GameAction) inPacket.getValue(); + gameAction.run(); + } + } + } + } + +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientSenderThread.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientSenderThread.java new file mode 100644 index 00000000..ec4e58fb --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientSenderThread.java @@ -0,0 +1,37 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import javafx.util.Pair; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.MessageType; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; + +public class ClientSenderThread extends Thread { + + private BlockingQueue> actionQueue = new LinkedBlockingQueue<>(); + + public void addActionTask(Pair gameAction) { + actionQueue.add(gameAction); + } + + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + List entityStates = MCClient.getClientState() + .getEntityStatesByOwnerId(MCClient.getClientId()); + Utils.delay(); + Sender sender = new Sender(); + if (!entityStates.isEmpty()) { + sender.send(MCClient.getClientSocket(), new Pair<>(MessageType.UPDATE, entityStates)); + } + while (!actionQueue.isEmpty()){ + Pair pair = actionQueue.poll(); + sender.send(MCClient.getClientSocket(),pair); + } + } + } + +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientThread.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientThread.java deleted file mode 100644 index 7c8a9691..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ClientThread.java +++ /dev/null @@ -1,89 +0,0 @@ -package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; - -import com.almasb.fxgl.dsl.FXGL; -import com.almasb.fxgl.entity.Entity; -import java.net.SocketAddress; -import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import javafx.geometry.Point2D; -import ru.nsu.fit.dib.projectdib.Factory; -import ru.nsu.fit.dib.projectdib.entity.weapons.WeaponFactory.Weapons; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.GameStatePacket; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.NewEntity; -import ru.nsu.fit.dib.projectdib.newMultiplayer.exeptions.PacketTypeException; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; - -public class ClientThread extends Thread { - - private final SocketAddress serverAddress; - - private final Sender sender; - - private final Receiver receiver; - - private final BlockingQueue newEntities = new LinkedBlockingQueue<>(); - - private final BlockingQueue spawnEntityList = new LinkedBlockingQueue<>(); - - private final Object monitor = new Object(); - - public ClientThread(Receiver receiver, Sender sender, SocketAddress serverAddress) { - this.serverAddress = serverAddress; - this.sender = sender; - this.receiver = receiver; - } - - public Entity spawnNewEntity(NewEntity newEntity) { - newEntities.add(newEntity); - while (true) { - synchronized (monitor) { - try { - monitor.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - } - Point2D entPos = newEntity.getPosition(); - Optional entity = spawnEntityList.stream().filter(e -> e.getPosition().equals(entPos)) - .findAny(); - if (entity.isPresent()) { - spawnEntityList.remove(entity.get()); - return entity.get(); - } - } - } - - @Override - public void run() { - while (!Thread.currentThread().isInterrupted()) { - List entityStates = MCClient.getClientState().getEntityStates(); - List newEntityList = new ArrayList<>(); - newEntities.drainTo(newEntityList); - if (entityStates.size() > 0) { - System.out.println(entityStates.get(0).getPosition()); - } - sender.send(serverAddress, new GameStatePacket(newEntityList, entityStates)); - try { - GameStatePacket gameStatePacket = receiver.receive(); - MCClient.getClientState().updateEntities(gameStatePacket.getAllCoordinatesOfEntitiesList()); - List entityList = MCClient.getClientState().spawnEntities(gameStatePacket.getNewEntityList()); - spawnEntityList.addAll(entityList); - synchronized (monitor) { - monitor.notifyAll(); - } - } catch (PacketTypeException e) { - throw new RuntimeException(e); - } catch (SocketTimeoutException e) { - throw new RuntimeException(e); - } - } - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerActionThread.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerActionThread.java new file mode 100644 index 00000000..112294ad --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerActionThread.java @@ -0,0 +1,47 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import javafx.util.Pair; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.MCServer; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.GameAction; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.SpawnAction; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.MessageType; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; + +public class ServerActionThread extends Thread { + + private BlockingQueue> actionQueue = new LinkedBlockingQueue<>(); + + private Integer nextEntityId = 10; + + public void addActionTask(Pair gameAction) { + actionQueue.add(gameAction); + } + + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + Pair inPacket = null; + try { + inPacket = actionQueue.take(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + assert inPacket != null; + Pair outPacket = switch (inPacket.getKey()) { + case SPAWN -> { + SpawnAction spawnAction = (SpawnAction) inPacket.getValue(); + spawnAction.getNewEntity().setWeaponId(nextEntityId++); + yield new Pair<>(MessageType.SPAWN, spawnAction); + } + default -> null; + }; + Sender sender = new Sender(); + MCServer.getClientSockets().values().forEach(s -> sender.send(s, outPacket)); + } + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerReceiverThread.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerReceiverThread.java new file mode 100644 index 00000000..683b5b4b --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerReceiverThread.java @@ -0,0 +1,31 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; + +import java.net.Socket; +import java.util.List; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.MCServer; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; + +public class ServerReceiverThread extends Thread { + + private final Receiver receiver; + + public ServerReceiverThread(Socket socket) { + this.receiver = new Receiver(socket); + } + + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + var inPacket = receiver.receive(); + switch (inPacket.getKey()) { + case UPDATE -> { + MCServer.getUpdaterThread().addUpdateTask((List) inPacket.getValue()); + } + default -> { + MCServer.getActionThread().addActionTask(inPacket); + } + } + } + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerThread.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerThread.java deleted file mode 100644 index 5aaa6da7..00000000 --- a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerThread.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; - -import java.net.SocketAddress; -import java.net.SocketTimeoutException; -import java.util.List; -import ru.nsu.fit.dib.projectdib.newMultiplayer.data.GameStatePacket; -import ru.nsu.fit.dib.projectdib.newMultiplayer.exeptions.PacketTypeException; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Receiver; -import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; - -public class ServerThread extends Thread { - - - private final Receiver receiver; - - private final Sender sender; - - private final List clientSockets; - - private Integer nextEntityId = 1; - - public ServerThread(Receiver receiver, Sender sender, List clientSockets) { - this.receiver = receiver; - this.sender = sender; - this.clientSockets = clientSockets; - } - - - @Override - public void run() { - while (!Thread.currentThread().isInterrupted()) { - GameStatePacket inPacket; - try { - inPacket = receiver.receive(); - } catch (PacketTypeException e) { - // TODO: 14.03.2023 обработка ошибки - continue; - } catch (SocketTimeoutException e) { - // сеть упала - throw new RuntimeException(e); - } - - // логика обработки пакета :) - inPacket.getNewEntityList().forEach(e -> { - e.setId(nextEntityId); - nextEntityId++; - }); - - GameStatePacket outPacket = inPacket; - - clientSockets.forEach(s -> sender.send(s, outPacket)); - } - } -} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerUpdaterThread.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerUpdaterThread.java new file mode 100644 index 00000000..84e9e8e6 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/ServerUpdaterThread.java @@ -0,0 +1,44 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.stream.Collectors; +import javafx.util.Pair; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.MCServer; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.MessageType; +import ru.nsu.fit.dib.projectdib.newMultiplayer.socket.Sender; + +public class ServerUpdaterThread extends Thread { + + private static final Integer SERVER_ID = -1; + + private BlockingQueue> updaterQueue = new LinkedBlockingQueue<>(); + + public void addUpdateTask(List list) { + updaterQueue.add(list); + } + + @Override + public void run() { + while (!Thread.currentThread().isInterrupted()) { + Utils.delay(); + List outList = MCClient.getClientState().getEntityStatesByOwnerId(SERVER_ID); + // TODO: 19.04.2023 Сделать нормальную проверку на наличие данных для передачи + // (пока что сервер все складывает в outList и проверяет на 0) + while (outList.size() == 0) { + outList = MCClient.getClientState().getEntityStatesByOwnerId(SERVER_ID); + List> clientsStates = new ArrayList<>(); + updaterQueue.drainTo(clientsStates); + clientsStates.forEach(outList::addAll); + } + Sender sender = new Sender(); + List finalOutList = outList; + MCServer.getClientSockets().values() + .forEach(s -> sender.send(s, new Pair<>(MessageType.UPDATE, finalOutList))); + } + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/Utils.java b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/Utils.java new file mode 100644 index 00000000..572ae1f2 --- /dev/null +++ b/src/main/java/ru/nsu/fit/dib/projectdib/newMultiplayer/threads/Utils.java @@ -0,0 +1,11 @@ +package ru.nsu.fit.dib.projectdib.newMultiplayer.threads; + +public class Utils { + public static void delay(){ + try { + Thread.sleep(1); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/ui/MainMenu.java b/src/main/java/ru/nsu/fit/dib/projectdib/ui/MainMenu.java index 47065860..2c0d0e94 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/ui/MainMenu.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/ui/MainMenu.java @@ -1,23 +1,38 @@ package ru.nsu.fit.dib.projectdib.ui; +import static java.lang.Thread.sleep; import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._campfireAnimationUI; import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._fontDustyPro; import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._forestAnimationUI; +import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._loadingAnimation; import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._menuButton; import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._menuSelectedButton; import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._returnButton; import static ru.nsu.fit.dib.projectdib.data.ProjectConfig._returnSelectedButton; +import static ru.nsu.fit.dib.projectdib.data.ProjectConfig.style; import com.almasb.fxgl.app.scene.FXGLMenu; import com.almasb.fxgl.app.scene.MenuType; import com.almasb.fxgl.dsl.FXGL; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; import java.net.SocketAddress; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import javafx.animation.Animation; import javafx.geometry.Pos; import javafx.geometry.Rectangle2D; +import javafx.scene.Node; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; @@ -27,13 +42,17 @@ import javafx.scene.layout.RowConstraints; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import javafx.scene.shape.Rectangle; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.util.Duration; +import ru.nsu.fit.dib.projectdib.connecting.tasks.ClientConnectionTask; import ru.nsu.fit.dib.projectdib.connecting.tasks.ServerConnectionTask; -import ru.nsu.fit.dib.projectdib.newMultiplayer.context.server.MCServer; +import ru.nsu.fit.dib.projectdib.data.ProjectConfig; +import ru.nsu.fit.dib.projectdib.newMultiplayer.config.ClientConfig; +import ru.nsu.fit.dib.projectdib.newMultiplayer.context.client.MCClient; import ru.nsu.fit.dib.projectdib.ui.UIElements.ImageButton; import ru.nsu.fit.dib.projectdib.ui.UIElements.SpriteAnimation; import ru.nsu.fit.dib.projectdib.ui.UIElements.WrappedImageView; @@ -106,10 +125,12 @@ public MainMenu(MenuType type) { campfire.setPreserveRatio(true); images.setAlignment(Pos.CENTER); images.getChildren().addAll(forest, campfire); + ImageView loading = new ImageView(new Image(_loadingAnimation)); //======================================[ Fonts ]======================================= ClassLoader classloader = Thread.currentThread().getContextClassLoader(); Font font = Font.loadFont(classloader.getResourceAsStream(_fontDustyPro), 65); Font bigFont = Font.loadFont(classloader.getResourceAsStream(_fontDustyPro), 140); + Font smallFont = Font.loadFont(classloader.getResourceAsStream(_fontDustyPro), 50); //=====================================[ GameName ]======================================= AnchorPane name = new AnchorPane(); @@ -132,6 +153,12 @@ public MainMenu(MenuType type) { Image unpushed = new Image(_menuButton, 1020, 180, true, false); Image pushed = new Image(_menuSelectedButton, 1020, 180, true, false); + Image unpushedEnter = new Image(_menuButton, 510, 90, true, false); + Image pushedEnter = new Image(_menuSelectedButton, 510, 90, true, false); + Image unpushedServer = new Image(_menuButton, 765, 135, true, false); + Image pushedServer = new Image(_menuSelectedButton, 765, 135, true, false); + Image unpushedUpdate = new Image(_menuButton, 510, 90, true, false); + Image pushedUpdate = new Image(_menuSelectedButton, 510, 90, true, false); Image unpushedReturn = new Image(_returnButton, 132, 132, true, false); Image pushedReturn = new Image(_returnSelectedButton, 132, 132, true, false); @@ -145,6 +172,18 @@ public MainMenu(MenuType type) { ImageButton connect = new ImageButton("Connect", font, "#5ae8a8", "#2b2944", pushed, unpushed); ImageButton server = new ImageButton("Create server", font, "#5ae8a8", "#2b2944", pushed, unpushed); + String gamePort = String.valueOf(ProjectConfig.SERVER_PORT); + ImageButton serverID = new ImageButton("Server: " + gamePort, smallFont, "#5ae8a8", "#2b2944", + pushedServer, + unpushedServer); + ImageButton startMultiplayer = new ImageButton("Start", smallFont, "#5ae8a8", "#2b2944", + pushedServer, + unpushedServer); + ImageButton update = new ImageButton("Update", smallFont, "#5ae8a8", "#2b2944", + pushedUpdate, + unpushedUpdate); + ImageButton enter = new ImageButton("Enter", font, "#5ae8a8", "#2b2944", pushedEnter, + unpushedEnter); //============================================================================================== ImageButton returnButton = new ImageButton("", font, "#5ae8a8", "#2b2944", pushedReturn, unpushedReturn); @@ -154,31 +193,138 @@ public MainMenu(MenuType type) { //=== ui.getChildren().addAll(space, start, multiplayer, settings); //=====================================[ Buttons Tree ]===================================== - TreeNode tree = new TreeNode<>(null, List.of(start, multiplayer, settings)); - tree.addNodes(multiplayer, List.of(connect, server)); + ///root/// + TreeNode tree = new TreeNode<>(null, List.of(start, multiplayer, settings)); //=====================================[ Buttons Handlers ]===================================== + //===Multiplayer=== multiplayer.setOnMouseClicked(event -> { globalAnchor.getChildren().add(returnButton); - ui.getChildren().removeAll(tree.getParentANChildren()); + ui.getChildren().removeAll(tree.getANChildren()); tree.changeActiveNode(multiplayer); + tree.addNodes(multiplayer, List.of(connect, server)); + ui.getChildren().addAll(tree.getANChildren()); + }); + + //===Create server=== + VBox serverBox = new VBox(); + serverBox.getChildren().addAll(update, startMultiplayer, serverID); + ScrollPane scrollPane = new ScrollPane(); + final Future>[] future = new Future[]{null}; + ServerConnectionTask serverConnectionTask = new ServerConnectionTask(); + server.setOnMouseClicked(event -> { + future[0] = CompletableFuture.supplyAsync(serverConnectionTask); + ui.getChildren().removeAll(tree.getANChildren()); + tree.changeActiveNode(server); + scrollPane.setPrefViewportHeight(600); + scrollPane.setContent(serverBox); + scrollPane.setStyle("-fx-background: transparent; -fx-background-color: transparent;"); + scrollPane.getStylesheets().add( + Objects.requireNonNull(this.getClass().getClassLoader().getResource(style)).toExternalForm()); + tree.addNodes(server, List.of(scrollPane)); + ui.getChildren().addAll(tree.getANChildren()); + }); + + //===Update=== + update.setOnMouseClicked(event -> { + ui.getChildren().removeAll(tree.getANChildren()); + tree.removeChildren(); + var clients = serverConnectionTask.getClientSockets(); + for (Entry s : clients.entrySet()) { + ImageButton newClient = new ImageButton(s.getValue().getInetAddress().toString().replaceFirst("/", ""), font, "#5ae8a8", + "#2b2944", + pushedServer, + unpushedServer); + if (!serverBox.getChildren().contains(newClient)) { + serverBox.getChildren().add(newClient); + } + } + scrollPane.setContent(serverBox); + tree.addNodes(server, List.of(scrollPane)); ui.getChildren().addAll(tree.getANChildren()); }); + + //===Start Multiplayer=== + startMultiplayer.setOnMouseClicked(e -> { + // TODO: 24.04.2023 шлём инициализационный пакет клиентам + FXGL.getGameController().startNewGame(); + }); + + + + //===Connect=== + TextField passwordField = new TextField(); + VBox authentication = new VBox(); + passwordField.setPrefSize(700, 100); + passwordField.setMinSize(700, 100); + passwordField.setMaxSize(700, 100); + passwordField.setFont(smallFont); + passwordField.setAlignment(Pos.CENTER); + passwordField.setPromptText("Enter game address"); + passwordField.setStyle("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%)"); + authentication.setAlignment(Pos.CENTER); + authentication.getChildren().add(passwordField); + authentication.getChildren().add(enter); + + connect.setOnMouseClicked(event -> { + ui.getChildren().removeAll(tree.getANChildren()); + tree.changeActiveNode(connect); + tree.addNodes(connect, List.of(authentication)); + ui.getChildren().add(authentication); + }); + + //===Enter=== + Text text1 = new Text("Please, wait for"); + Text text2 = new Text("the game to start"); + text1.setFont(smallFont); + text2.setFont(smallFont); + text1.setFill(Color.WHITE); + text2.setFill(Color.WHITE); + VBox loadingBox = new VBox(); + loadingBox.getChildren().add(loading); + loadingBox.getChildren().add(text1); + loadingBox.getChildren().add(text2); + loadingBox.setAlignment(Pos.CENTER); + + enter.setOnMouseClicked(event -> { + SocketAddress socketAddress; + try { + socketAddress = new InetSocketAddress(passwordField.getText().split(":")[0], Integer.parseInt(passwordField.getText().split(":")[1])); + } catch (Exception e) { + passwordField.clear(); + passwordField.setPromptText("Wrong address!"); + passwordField.setStyle("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%)"); + return; + } + Future clientFuture = CompletableFuture.supplyAsync(new ClientConnectionTask(socketAddress)); + try { + if (clientFuture.get() == null) { + passwordField.clear(); + passwordField.setPromptText("Wrong address!"); + passwordField.setStyle("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%)"); + } else { + ui.getChildren().removeAll(tree.getANChildren()); + tree.changeActiveNode(authentication); + tree.addNodes(authentication, List.of(loadingBox)); + ui.getChildren().add(loadingBox); + } + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }); + //===Start=== start.setOnMouseClicked(event -> FXGL.getGameController().startNewGame()); - //===Server=== - server.setOnMouseClicked(event->{}); + //===Settings=== settings.setOnMouseClicked(event -> { }); - //==Server== - //AtomicReference>> serverConnectionFuture = new AtomicReference<>(); - //ServerConnectionTask serverConnectionTask = new ServerConnectionTask(MCServer.getServerSocket()); - //server.setOnMouseClicked(event -> serverConnectionFuture.set(CompletableFuture.supplyAsync(serverConnectionTask))); + //===Return=== returnButton.setOnMouseClicked(event -> { - ui.getChildren().removeAll(tree.getParentANChildren()); - tree.changeActiveNode(tree.getRoot()); + ui.getChildren().removeAll(tree.getANChildren()); + tree.removeChildren(); + tree.changeActiveNode(tree.getParentA()); if (tree.getRoot() == tree.getParentAN()) { globalAnchor.getChildren().remove(returnButton); } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/ui/TreeNode.java b/src/main/java/ru/nsu/fit/dib/projectdib/ui/TreeNode.java index 2892a3d8..ab2263a5 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/ui/TreeNode.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/ui/TreeNode.java @@ -28,6 +28,7 @@ public TreeNode(T root) { } private TreeNode(TreeNode parent, T root) { + this.leafs = new ArrayList<>(); this.parent = parent; this.root = root; } @@ -41,6 +42,7 @@ private TreeNode(TreeNode parent, T root) { public TreeNode(T root, List leafs) { parent = this; activeNode = this; + this.leafs = new ArrayList<>(); addNodes(leafs); this.root = root; } @@ -71,9 +73,10 @@ private TreeNode getNode(T value) { } private void addNodes(List branchLeafs) { - leafs = new ArrayList<>(); + //leafs = new ArrayList<>(); branchLeafs.forEach(leaf -> { - this.leafs.add(new TreeNode<>(leaf)); + TreeNode branchLeaf = new TreeNode<>(this, leaf); + this.leafs.add(branchLeaf); }); } @@ -88,6 +91,13 @@ public void addNodes(T branchRoot, List branchLeafs) { localRoot.addNodes(branchLeafs); } + public void removeChildren() { + for (TreeNode leaf : activeNode.leafs) { + leaf.parent = null; + } + activeNode.leafs.clear(); + } + /** * Сменить активную вершину * @@ -97,6 +107,10 @@ public void changeActiveNode(T node) { activeNode = getNode(node); } + public void changeActiveNode(TreeNode node) { + activeNode = node; + } + private List getChildren() { List list = new ArrayList<>(); leafs.forEach(nowNode -> { @@ -114,6 +128,7 @@ public List getParentANChildren() { return activeNode.parent.getChildren(); } + /** * Получить детей активной Node * @@ -131,4 +146,10 @@ public List getANChildren() { public T getParentAN() { return activeNode.root; } + + + public TreeNode getParentA() { + return activeNode.parent; + } + } diff --git a/src/main/java/ru/nsu/fit/dib/projectdib/ui/UIElements/ImageButton.java b/src/main/java/ru/nsu/fit/dib/projectdib/ui/UIElements/ImageButton.java index 1f4c9f58..9d3954e8 100644 --- a/src/main/java/ru/nsu/fit/dib/projectdib/ui/UIElements/ImageButton.java +++ b/src/main/java/ru/nsu/fit/dib/projectdib/ui/UIElements/ImageButton.java @@ -1,5 +1,6 @@ package ru.nsu.fit.dib.projectdib.ui.UIElements; +import java.util.Objects; import javafx.geometry.Pos; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -54,4 +55,20 @@ public ImageButton(String name, Font font, String unpushedColor, String pushedCo private void setImage(Image image) { iv.setImage(image); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ImageButton that)) { + return false; + } + return text.getText().equals(that.text.getText()); + } + + @Override + public int hashCode() { + return Objects.hash(text.getText()); + } } diff --git a/src/main/resources/assets/UI/elements/loadingAnimation.gif b/src/main/resources/assets/UI/elements/loadingAnimation.gif new file mode 100644 index 00000000..2816d713 Binary files /dev/null and b/src/main/resources/assets/UI/elements/loadingAnimation.gif differ diff --git a/src/main/resources/assets/UI/elements/style.css b/src/main/resources/assets/UI/elements/style.css new file mode 100644 index 00000000..55309261 --- /dev/null +++ b/src/main/resources/assets/UI/elements/style.css @@ -0,0 +1,20 @@ +.scroll-bar:vertical .track{ + -fx-background-color :#000000; + -fx-background-radius : 0.0em; +} + +.scroll-bar:vertical .thumb { + -fx-background-color :white; + -fx-background-insets : 2.0, 0.0, 0.0; + -fx-background-radius : 0.0em; +} + +.scroll-bar:vertical .increment-button { + -fx-background-color : #000000; + -fx-background-insets : 0 0 0 0, 0 0 0 0, 0 0 0 0; +} + +.scroll-bar:vertical .decrement-button { + -fx-background-color : #000000; + -fx-background-insets : 0 0 0 0, 0 0 0 0, 0 0 0 0; +} \ No newline at end of file diff --git a/src/test/java/FlatBurrersTest.java b/src/test/java/FlatBurrersTest.java new file mode 100644 index 00000000..5381f3bc --- /dev/null +++ b/src/test/java/FlatBurrersTest.java @@ -0,0 +1,72 @@ +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import javafx.geometry.Point2D; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import ru.nsu.fit.dib.projectdib.entity.creatures.HeroesFactory.HeroType; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.serialization.FBSDeserializer; +import ru.nsu.fit.dib.projectdib.flatbuffersclasses.serialization.FBSSerializer; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.EntityState; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.NewEntity; +import ru.nsu.fit.dib.projectdib.newMultiplayer.data.actions.SpawnAction; + +class FlatBurrersTest { + + @Test + void UpdateDataTest(){ + List list = new ArrayList<>(); + list.add(new EntityState(1,new Point2D(1,4),new Point2D(3,1),2)); + //list.add(new EntityState(3,new Point2D(5,6),new Point2D(6,3),4)); + //list.add(new EntityState(5,new Point2D(2,2),new Point2D(3,8),1)); + + ByteBuffer buffer = FBSSerializer.serialize(list); + + buffer.compact().position(0); + int size = buffer.remaining(); + byte[] data = new byte[size]; + buffer.get(data); + //===================== + ByteBuffer byteBuffer = ByteBuffer.allocate(data.length); + byteBuffer.put(data); + + + List newList = FBSDeserializer.deserializeEntityStateList(byteBuffer.flip()); + for(int i=0;i<1;i++){ + Assertions.assertEquals(list.get(i).getId(),newList.get(i).getId()); + Assertions.assertEquals(list.get(i).getPosition().getX(),newList.get(i).getPosition().getX()); + Assertions.assertEquals(list.get(i).getPosition().getY(),newList.get(i).getPosition().getY()); + Assertions.assertEquals(list.get(i).getRotation().getX(),newList.get(i).getRotation().getX()); + Assertions.assertEquals(list.get(i).getRotation().getY(),newList.get(i).getRotation().getY()); + Assertions.assertEquals(list.get(i).getActiveWeapon(),newList.get(i).getActiveWeapon()); + } + } + @Test + void SpawnDataTest(){ + EntityState state = new EntityState(123,new Point2D(12,23),new Point2D(34,45),1234); + NewEntity newEntity = new NewEntity(HeroType.Elf.name(), 234,state); + SpawnAction sa = new SpawnAction(newEntity); + ByteBuffer buffer = FBSSerializer.serialize(sa); + + buffer.compact().position(0); + int size = buffer.remaining(); + byte[] data = new byte[size]; + buffer.get(data); + //===================== + ByteBuffer byteBuffer = ByteBuffer.allocate(data.length); + byteBuffer.put(data); + SpawnAction newSA = FBSDeserializer.deserializeSpawnAction(byteBuffer.flip()); + + Assertions.assertEquals(sa.getNewEntity().getSeed(),newSA.getNewEntity().getSeed()); + Assertions.assertEquals(sa.getNewEntity().getID(),newSA.getNewEntity().getID()); + Assertions.assertEquals(sa.getNewEntity().getWeaponId(),newSA.getNewEntity().getWeaponId()); + Assertions.assertEquals(sa.getNewEntity().getEntityType(),newSA.getNewEntity().getEntityType()); + + + Assertions.assertEquals(sa.getNewEntity().getState().getPosition(),newSA.getNewEntity().getState().getPosition()); + Assertions.assertEquals(sa.getNewEntity().getState().getRotation(),newSA.getNewEntity().getState().getRotation()); + Assertions.assertEquals(sa.getNewEntity().getState().getId(),newSA.getNewEntity().getState().getId()); + Assertions.assertEquals(sa.getNewEntity().getState().getActiveWeapon(),newSA.getNewEntity().getState().getActiveWeapon()); + } + +}