diff --git a/annotations/src/io/anuke/annotations/RemoteReadGenerator.java b/annotations/src/io/anuke/annotations/RemoteReadGenerator.java index c96661a9af..e1c381aa89 100644 --- a/annotations/src/io/anuke/annotations/RemoteReadGenerator.java +++ b/annotations/src/io/anuke/annotations/RemoteReadGenerator.java @@ -107,31 +107,17 @@ public class RemoteReadGenerator { } } + //execute the relevant method before the forward + //if it throws a ValidateException, the method won't be forwarded + readBlock.addStatement("$N." + entry.element.getSimpleName() + "(" + varResult.toString() + ")", ((TypeElement) entry.element.getEnclosingElement()).getQualifiedName().toString()); - - //begin lambda control flow - readBlock.beginControlFlow("com.badlogic.gdx.Gdx.app.postRunnable(() -> "); - - //call forwarded method before the method, so if it throws a ValidateException, the method won't be forwarded - if(entry.forward && entry.where.isServer){ - //try block to catch validate exception - readBlock.beginControlFlow("try"); - + //call forwarded method, don't forward on the client reader + if(entry.forward && entry.where.isServer && needsPlayer){ //call forwarded method readBlock.addStatement(packageName + "." + entry.className + "." + entry.element.getSimpleName() + "__forward(player.clientid" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")"); - - //when a ValidateException is caught, print the error and return - readBlock.nextControlFlow("catch (io.anuke.mindustry.net.ValidateException e)"); - readBlock.addStatement("e.printStackTrace()"); - readBlock.addStatement("return"); - readBlock.endControlFlow(); } - //execute the relevant method - readBlock.addStatement("$N." + entry.element.getSimpleName() + "(" + varResult.toString() + ")", ((TypeElement) entry.element.getEnclosingElement()).getQualifiedName().toString()); - //end lambda - readBlock.endControlFlow(")"); } //end control flow if necessary diff --git a/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java b/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java index 2ca0c75932..07edbb2752 100644 --- a/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java +++ b/annotations/src/io/anuke/annotations/RemoteWriteGenerator.java @@ -65,9 +65,14 @@ public class RemoteWriteGenerator { //create builder MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.SYNCHRONIZED) + .addModifiers(Modifier.STATIC, Modifier.SYNCHRONIZED) .returns(void.class); + //forwarded methods aren't intended for use, and are not public + if(!forwarded){ + method.addModifiers(Modifier.PUBLIC); + } + //validate client methods to make sure if(methodEntry.where.isClient){ if(elem.getParameters().isEmpty()){ @@ -173,7 +178,11 @@ public class RemoteWriteGenerator { String sendString; if(forwarded){ //forward packet - sendString = "sendExcept(exceptSenderID, "; + if(!methodEntry.local.isClient){ //if the client doesn't get it called locally, forward it back after validation + sendString = "send("; + }else { + sendString = "sendExcept(exceptSenderID, "; + } }else if(toAll){ //send to all players / to server sendString = "send("; }else{ //send to specific client from server diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 96a885ce87..239f048473 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -5,10 +5,12 @@ import com.badlogic.gdx.utils.Queue; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.fx.BlockFx; +import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.effect.ItemTransfer; import io.anuke.mindustry.game.EventType.BlockBuildEvent; +import io.anuke.mindustry.gen.CallBlocks; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Recipe; @@ -135,7 +137,8 @@ public interface BuilderTrait { unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.drawx(), tile.drawy()), 0.4f); if(current.progress >= 1f){ - Build.breakBlock(unit.getTeam(), current.x, current.y, true, true); + //FIXME a player instace is required here, but the the builder may not be a player + CallBlocks.breakBlock(unit instanceof Player ? (Player)unit : null, unit.getTeam(), current.x, current.y, true, true); } }else{ //otherwise, skip it @@ -145,9 +148,10 @@ public interface BuilderTrait { if (!(tile.block() instanceof BuildBlock)) { //check if haven't started placing if(Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){ //if it's valid, place it - Build.placeBlock(unit.getTeam(), current.x, current.y, current.recipe, current.rotation); + //FIXME a player instace is required here, but the the builder may not be a player + CallBlocks.placeBlock(unit instanceof Player ? (Player)unit : null, unit.getTeam(), current.x, current.y, current.recipe, current.rotation); - //fire place event. + //fire build event threads.run(() -> Events.fire(BlockBuildEvent.class, unit.getTeam(), world.tile(current.x, current.y))); }else{ //otherwise, skip it diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index 2109778e5c..0cdee190ff 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -3,7 +3,10 @@ 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.game.Team; import io.anuke.mindustry.net.Packets.KickReason; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.type.Upgrade; import io.anuke.mindustry.type.Weapon; import io.anuke.mindustry.world.Tile; @@ -47,6 +50,16 @@ public class TypeIO { return KickReason.values()[buffer.get()]; } + @WriteClass(Team.class) + public static void writeTeam(ByteBuffer buffer, Team reason){ + buffer.put((byte)reason.ordinal()); + } + + @ReadClass(Team.class) + public static Team readTeam(ByteBuffer buffer){ + return Team.values()[buffer.get()]; + } + @WriteClass(Weapon.class) public static void writeWeapon(ByteBuffer buffer, Weapon weapon){ buffer.put(weapon.id); @@ -57,6 +70,26 @@ public class TypeIO { return Upgrade.getByID(buffer.get()); } + @WriteClass(Item.class) + public static void writeItem(ByteBuffer buffer, Item item){ + buffer.put((byte)item.id); + } + + @ReadClass(Item.class) + public static Item readItem(ByteBuffer buffer){ + return Item.getByID(buffer.get()); + } + + @WriteClass(Recipe.class) + public static void writeRecipe(ByteBuffer buffer, Recipe recipe){ + buffer.put((byte)recipe.id); + } + + @ReadClass(Recipe.class) + public static Recipe readRecipe(ByteBuffer buffer){ + return Recipe.getByID(buffer.get()); + } + @WriteClass(String.class) public static void writeString(ByteBuffer buffer, String string){ if(string != null) { diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 9028092d88..bdc2ee8797 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -2,10 +2,16 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.utils.Array; +import io.anuke.annotations.Annotations.Loc; +import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.fx.Fx; +import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.net.In; +import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import io.anuke.ucore.core.Effects; @@ -20,7 +26,13 @@ public class Build { private static Array tempTiles = new Array<>(); /**Returns block type that was broken, or null if unsuccesful.*/ - public static Block breakBlock(Team team, int x, int y, boolean effect, boolean sound){ + @Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks) + public static Block breakBlock(Player player, Team team, int x, int y, boolean effect, boolean sound){ + + if(Net.server() && !validBreak(team, x, y)){ + throw new ValidateException(player, "An invalid block has been broken."); + } + Tile tile = world.tile(x, y); if(tile == null) return null; @@ -47,7 +59,13 @@ public class Build { } /**Places a BuildBlock at this location. Call validPlace first.*/ - public static void placeBlock(Team team, int x, int y, Recipe recipe, int rotation){ + @Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks) + public static void placeBlock(Player player, Team team, int x, int y, Recipe recipe, int rotation){ + + if(Net.server() && !validPlace(team, x, y, recipe.result, rotation)){ + throw new ValidateException(player, "An invalid block has been placed."); + } + Tile tile = world.tile(x, y); Block result = recipe.result; Block previous = tile.block(); @@ -148,6 +166,5 @@ public class Build { return tile != null && !tile.block().unbreakable && (!tile.isLinked() || !tile.getLinked().block().unbreakable) && tile.breakable() && (tile.getTeam() == Team.none || tile.getTeam() == team); - } } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java index 3fc0680b3a..d4bb6e280f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java @@ -1,7 +1,12 @@ package io.anuke.mindustry.world.blocks.distribution; +import io.anuke.annotations.Annotations.Loc; +import io.anuke.annotations.Annotations.Remote; import io.anuke.mindustry.content.Items; +import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.gen.CallBlocks; +import io.anuke.mindustry.net.In; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -95,7 +100,7 @@ public class Sorter extends Block implements SelectionTrait{ @Override public void buildTable(Tile tile, Table table){ SorterEntity entity = tile.entity(); - buildItemTable(table, () -> entity.sortItem, item -> entity.sortItem = item); + buildItemTable(table, () -> entity.sortItem, item -> CallBlocks.setSorterItem(null, tile, item)); } @Override @@ -103,6 +108,12 @@ public class Sorter extends Block implements SelectionTrait{ return new SorterEntity(); } + @Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true) + public static void setSorterItem(Player player, Tile tile, Item item){ + SorterEntity entity = tile.entity(); + entity.sortItem = item; + } + public static class SorterEntity extends TileEntity{ public Item sortItem = Items.iron;