From d5a58be44063f4f09987276a3c245ec562ca0288 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 9 Jun 2018 17:05:47 -0400 Subject: [PATCH] Updated uCore, fixed GWT build, better client snapshot system --- .../RemoteMethodAnnotationProcessor.java | 4 +- .../annotations/RemoteWriteGenerator.java | 10 ++-- build.gradle | 8 +++- core/src/Mindustry.gwt.xml | 3 +- .../io/anuke/mindustry/core/NetClient.java | 1 - .../io/anuke/mindustry/core/NetServer.java | 10 ++-- .../io/anuke/mindustry/entities/Player.java | 14 ++++++ .../entities/effect/ItemTransfer.java | 19 +++++++- core/src/io/anuke/mindustry/io/TypeIO.java | 15 ++++++ core/src/io/anuke/mindustry/net/EditLog.java | 4 -- .../src/io/anuke/mindustry/net/NetworkIO.java | 19 ++++++++ core/src/io/anuke/mindustry/net/Packets.java | 46 ++++++------------- .../ui/fragments/BlockInventoryFragment.java | 21 +++++++-- .../ui/fragments/PlayerListFragment.java | 3 +- core/src/io/anuke/mindustry/world/Build.java | 3 +- .../world/blocks/storage/CoreBlock.java | 4 +- 16 files changed, 125 insertions(+), 59 deletions(-) diff --git a/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java b/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java index d08b6bc3ba..6fbab08303 100644 --- a/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java +++ b/annotations/src/io/anuke/annotations/RemoteMethodAnnotationProcessor.java @@ -98,7 +98,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor { //can't generate none methods if (annotation.targets() == Loc.none) { - Utils.messager.printMessage(Kind.ERROR, "A @Remote method's where() cannot be equal to 'none':", element); + Utils.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element); } //get and create class entry if needed @@ -106,6 +106,8 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor { ClassEntry clas = new ClassEntry(annotation.in()); classMap.put(annotation.in(), clas); classes.add(clas); + + Utils.messager.printMessage(Kind.NOTE, "Generating class '" + clas.name + "'."); } ClassEntry entry = classMap.get(annotation.in()); diff --git a/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java b/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java index 3ab0d2c3bb..a2f1e43768 100644 --- a/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java +++ b/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java @@ -28,7 +28,6 @@ public class RemoteWriteGenerator { for(ClassEntry entry : entries){ //create builder - System.out.println("Generating class! " + entry.name); TypeSpec.Builder classBuilder = TypeSpec.classBuilder(entry.name).addModifiers(Modifier.PUBLIC); //add temporary write buffer @@ -107,7 +106,12 @@ public class RemoteWriteGenerator { int index = 0; StringBuilder results = new StringBuilder(); for(VariableElement var : elem.getParameters()){ - results.append(var.getSimpleName()); + //special case: calling local-only methods uses the local player + if(index == 0 && methodEntry.where == Loc.client){ + results.append("io.anuke.mindustry.Vars.players[0]"); + }else { + results.append(var.getSimpleName()); + } if(index != elem.getParameters().size() - 1) results.append(", "); index ++; } @@ -151,7 +155,7 @@ public class RemoteWriteGenerator { //captialized version of type name for writing primitives String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1); //special case: method can be called from anywhere to anywhere - //thus, only write the player when the SERVER is writing data, since the client is the only one who reads that + //thus, only write the player when the SERVER is writing data, since the client is the only one who reads it boolean writePlayerSkipCheck = methodEntry.where == Loc.both && methodEntry.local == Loc.both && i == 0; if(writePlayerSkipCheck){ //write begin check diff --git a/build.gradle b/build.gradle index df27866a67..7e1dbd6b06 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ allprojects { gdxVersion = '1.9.8' roboVMVersion = '2.3.0' aiVersion = '1.8.1' - uCoreVersion = 'a91031d' + uCoreVersion = 'f0adaff' getVersionString = { String buildVersion = getBuildVersion() @@ -97,6 +97,8 @@ project(":html") { dependencies { compile project(":core") + compileOnly project(":annotations") + compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion" compile "com.badlogicgames.gdx:gdx:$gdxVersion:sources" compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion:sources" @@ -108,6 +110,10 @@ project(":html") { compile "com.sksamuel.gwt:gwt-websockets:1.0.4" compile "com.sksamuel.gwt:gwt-websockets:1.0.4:sources" } + + compileJava.options.compilerArgs = [ + "-processor", "io.anuke.annotations.RemoteMethodAnnotationProcessor" + ] } project(":android") { diff --git a/core/src/Mindustry.gwt.xml b/core/src/Mindustry.gwt.xml index 2f73583bb5..4da9038d49 100644 --- a/core/src/Mindustry.gwt.xml +++ b/core/src/Mindustry.gwt.xml @@ -2,6 +2,7 @@ + @@ -15,7 +16,7 @@ - + diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 4637a5679a..fc7fe6e474 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -165,7 +165,6 @@ public class NetClient extends Module { ClientSnapshotPacket packet = Pools.obtain(ClientSnapshotPacket.class); packet.lastSnapshot = lastSnapshotID; packet.snapid = lastSent++; - packet.player = player; Net.send(packet, SendMode.udp); } diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 12da6a3a1d..60fbe83c03 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -141,13 +141,9 @@ public class NetServer extends Module{ NetConnection connection = Net.getConnection(id); if(player == null || connection == null || packet.snapid < connection.lastRecievedSnapshot) return; - try { - player.read(packet.in, packet.timeSent); - connection.lastSnapshotID = packet.lastSnapshot; - connection.lastRecievedSnapshot = packet.snapid; - }catch (IOException e){ - e.printStackTrace(); - } + player.getInterpolator().read(player.x, player.y, packet.x, packet.y, packet.timeSent, packet.rotation, packet.baseRotation); + connection.lastSnapshotID = packet.lastSnapshot; + connection.lastRecievedSnapshot = packet.snapid; }); Net.handleServer(InvokePacket.class, (id, packet) -> RemoteReadServer.readPacket(packet.writeBuffer, packet.type, connections.get(id))); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 44693036a3..1645ecdafb 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -89,6 +89,19 @@ public class Player extends Unit implements BuilderTrait, CarryTrait { //region unit and event overrides, utility methods + @Override + public void interpolate() { + super.interpolate(); + + if(interpolator.values.length > 1){ + baseRotation = interpolator.values[1]; + } + + if(interpolator.target.dst(interpolator.last) > 1f){ + walktime += Timers.delta(); + } + } + @Override public CarriableTrait getCarry() { return carrying; @@ -568,6 +581,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait { return control.input(playerIndex).canShoot() && control.input(playerIndex).isShooting() && inventory.hasAmmo(); } + @Override public Queue getPlaceQueue(){ return placeQueue; } diff --git a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java index 6eea5e77cb..0253dad44d 100644 --- a/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java +++ b/core/src/io/anuke/mindustry/entities/effect/ItemTransfer.java @@ -3,17 +3,21 @@ package io.anuke.mindustry.entities.effect; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Pools; +import io.anuke.annotations.Annotations.Loc; +import io.anuke.annotations.Annotations.Remote; +import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Item; import io.anuke.ucore.entities.EntityGroup; -import io.anuke.ucore.entities.trait.DrawTrait; import io.anuke.ucore.entities.impl.TimedEntity; +import io.anuke.ucore.entities.trait.DrawTrait; +import io.anuke.ucore.entities.trait.PosTrait; import io.anuke.ucore.function.Callable; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Fill; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.entities.trait.PosTrait; import static io.anuke.mindustry.Vars.effectGroup; @@ -26,6 +30,17 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{ private PosTrait to; private Callable done; + @Remote(in = In.entities, called = Loc.server, unreliable = true) + public static void transferAmmo(Item item, float x, float y, Unit to){ + to.addAmmo(item); + create(item, x, y, to, () -> {}); + } + + @Remote(in = In.entities, called = Loc.server, unreliable = true) + public static void transferItemEffect(Item item, float x, float y, Unit to){ + create(item, x, y, to, () -> {}); + } + public static void create(Item item, float fromx, float fromy, PosTrait to, Callable done){ ItemTransfer tr = Pools.obtain(ItemTransfer.class); tr.item = item; diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index 95309c4611..8f7d37a54f 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.io; import io.anuke.annotations.Annotations.ReadClass; import io.anuke.annotations.Annotations.WriteClass; import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Packets.KickReason; import io.anuke.mindustry.type.Item; @@ -10,6 +11,7 @@ import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.type.Upgrade; import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.entities.Entities; import java.nio.ByteBuffer; @@ -34,6 +36,19 @@ public class TypeIO { return id == -1 ? null : playerGroup.getByID(id); } + @WriteClass(Unit.class) + public static void writeUnit(ByteBuffer buffer, Unit unit){ + buffer.put((byte)unit.getGroup().getID()); + buffer.putInt(unit.getID()); + } + + @ReadClass(Unit.class) + public static Unit writeUnit(ByteBuffer buffer){ + byte gid = buffer.get(); + int id = buffer.getInt(); + return (Unit)Entities.getGroup(gid).getByID(id); + } + @WriteClass(Tile.class) public static void writeTile(ByteBuffer buffer, Tile tile){ buffer.putInt(tile.packedPosition()); diff --git a/core/src/io/anuke/mindustry/net/EditLog.java b/core/src/io/anuke/mindustry/net/EditLog.java index 4ff06d565e..33d1eb42e1 100644 --- a/core/src/io/anuke/mindustry/net/EditLog.java +++ b/core/src/io/anuke/mindustry/net/EditLog.java @@ -15,10 +15,6 @@ public class EditLog { this.action = action; } - public String info() { - return String.format("Player: %s, Block: %s, Rotation: %s, Edit Action: %s", playername, block.name(), rotation, action.toString()); - } - public enum EditAction { PLACE, BREAK } diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index 3a13960d3a..e7645bac63 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.net; import com.badlogic.gdx.utils.ObjectMap; +import com.badlogic.gdx.utils.ObjectMap.Entry; import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.entities.Player; @@ -36,6 +37,14 @@ public class NetworkIO { stream.writeByte(state.mode.ordinal()); //gamemode stream.writeUTF(world.getMap().name); //map name + //write tags + ObjectMap tags = world.getMap().meta.tags; + stream.writeByte(tags.size); + for(Entry entry : tags.entries()){ + stream.writeUTF(entry.key); + stream.writeUTF(entry.value); + } + stream.writeInt(state.wave); //wave stream.writeFloat(state.wavetime); //wave countdown @@ -109,6 +118,14 @@ public class NetworkIO { //general state byte mode = stream.readByte(); String map = stream.readUTF(); + ObjectMap tags = new ObjectMap<>(); + + byte tagSize = stream.readByte(); + for (int i = 0; i < tagSize; i++) { + String key = stream.readUTF(); + String value = stream.readUTF(); + tags.put(key, value); + } int wave = stream.readInt(); float wavetime = stream.readFloat(); @@ -135,6 +152,8 @@ public class NetworkIO { //TODO send advanced map meta such as author, etc //TODO scan for cores Map currentMap = new Map(map, new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null); + currentMap.meta.tags.clear(); + currentMap.meta.tags.putAll(tags); world.setMap(currentMap); Tile[][] tiles = world.createTiles(width, height); diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 82962ddd1a..2ead39114d 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -1,15 +1,13 @@ package io.anuke.mindustry.net; import com.badlogic.gdx.utils.TimeUtils; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.io.Version; import io.anuke.mindustry.net.Packet.ImportantPacket; import io.anuke.mindustry.net.Packet.UnimportantPacket; -import io.anuke.ucore.io.ByteBufferInput; -import io.anuke.ucore.io.ByteBufferOutput; import io.anuke.ucore.io.IOUtils; -import java.io.IOException; import java.nio.ByteBuffer; /**Class for storing all packets.*/ @@ -96,54 +94,38 @@ public class Packets { } public static class ClientSnapshotPacket implements Packet{ - /**For writing only.*/ - public Player player; - + //snapshot meta public int lastSnapshot; public int snapid; - public int length; public long timeSent; - - public byte[] bytes; - public ByteBuffer result; - public ByteBufferInput in; + //player snapshot data + public float x, y, rotation, baseRotation; @Override public void write(ByteBuffer buffer) { - ByteBufferOutput out = new ByteBufferOutput(buffer); + Player player = Vars.players[0]; buffer.putInt(lastSnapshot); buffer.putInt(snapid); buffer.putLong(TimeUtils.millis()); - int position = buffer.position(); - try { - player.write(out); - length = buffer.position() - position; - buffer.position(position); - buffer.putInt(length); - player.write(out); - }catch (IOException e){ - e.printStackTrace(); - } + buffer.putFloat(player.x); + buffer.putFloat(player.y); + //saving 4 bytes, yay? + buffer.putShort((short)(player.rotation*2)); + buffer.putShort((short)(player.baseRotation*2)); } @Override public void read(ByteBuffer buffer) { - lastSnapshot = buffer.getInt(); snapid = buffer.getInt(); timeSent = buffer.getLong(); - length = buffer.getInt(); - if(bytes == null || bytes.length != length){ - bytes = new byte[length]; - result = ByteBuffer.wrap(bytes); - in = new ByteBufferInput(result); - } - - buffer.get(bytes); - result.position(0); + x = buffer.getFloat(); + y = buffer.getFloat(); + rotation = buffer.getShort()/2f; + baseRotation = buffer.getShort()/2f; } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java index 590350b1fb..655bfd7438 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -4,10 +4,14 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.IntSet; +import io.anuke.annotations.Annotations.Loc; +import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; -import io.anuke.mindustry.entities.effect.ItemTransfer; +import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.CallEntity; import io.anuke.mindustry.input.InputHandler; +import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.ui.ItemImage; import io.anuke.mindustry.world.Tile; @@ -106,12 +110,14 @@ public class BlockInventoryFragment implements Fragment { image.tapped(() -> { if(!canPick.get() || items[f] == 0) return; int amount = Math.min(Inputs.keyDown("item_withdraw") ? items[f] : 1, player.inventory.itemCapacityUsed(item)); - tile.block().removeStack(tile, item, amount); + + /* tile.block().removeStack(tile, item, amount); player.inventory.addItem(item, amount); for(int j = 0; j < Mathf.clamp(amount/3, 1, 8); j ++){ Timers.run(j*3f, () -> ItemTransfer.create(item, tile.drawx(), tile.drawy(), player, () -> {})); - } + }*/ + CallBlocks.requestItem(tile, item, amount); }); table.add(image); @@ -142,4 +148,13 @@ public class BlockInventoryFragment implements Fragment { table.setPosition(v.x, v.y, Align.center); } + @Remote(called = Loc.server, targets = Loc.client, in = In.blocks) + public static void requestItem(Player player, Tile tile, Item item, int amount){ + int removed = tile.block().removeStack(tile, item, amount); + + player.inventory.addItem(item, removed); + for(int j = 0; j < Mathf.clamp(removed/3, 1, 8); j ++){ + Timers.run(j*3f, () -> CallEntity.transferItemEffect(item, tile.drawx(), tile.drawy(), player)); + } + } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java index 3f39563509..ca2219ce7c 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -218,7 +218,8 @@ public class PlayerListFragment implements Fragment{ else { for(int i = 0; i < currentEditLogs.size; i++) { EditLog log = currentEditLogs.get(i); - table.add("[gold]" + (i + 1) + ". [white]" + log.info()).left(); + //TODO display log info. + table.add("[gold]" + (i + 1) + ". [white]INVALID").left(); table.row(); } } diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index f0d02a1685..d29d17ded4 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -75,7 +75,8 @@ public class Build { if(tile == null) return; //remote players only (?) - if(player.getPlaceQueue().size == 0){ + if(false){ + player.getPlaceQueue().clear(); player.getPlaceQueue().addFirst(new BuildRequest(x, y, rotation, recipe)); } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index 19eb3f275f..11eccaccd9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -10,8 +10,8 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.effect.ItemTransfer; import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.gen.CallEntity; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.net.In; @@ -180,7 +180,7 @@ public class CoreBlock extends StorageBlock { if(tile.entity.items.items[i] > 0 && unit.acceptsAmmo(item)){ tile.entity.items.items[i] --; unit.addAmmo(item); - ItemTransfer.create(item, tile.drawx(), tile.drawy(), unit, () -> {}); + CallEntity.transferAmmo(item, tile.drawx(), tile.drawy(), unit); return; } }