Updated uCore, fixed GWT build, better client snapshot system

This commit is contained in:
Anuken
2018-06-09 17:05:47 -04:00
parent b33dd7e91c
commit d5a58be440
16 changed files with 125 additions and 59 deletions

View File

@ -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());

View File

@ -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

View File

@ -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") {

View File

@ -2,6 +2,7 @@
<module>
<source path="io/anuke/mindustry" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Tile" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.Content" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.Maps" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.Player" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.units.BaseUnit" />
@ -15,7 +16,7 @@
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Packets" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Packet" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.effect" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.Bullet" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.bullet.Bullet" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.type.Recipe" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Streamable" />
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.meta.BlockBar" />

View File

@ -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);
}

View File

@ -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)));

View File

@ -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<BuildRequest> getPlaceQueue(){
return placeQueue;
}

View File

@ -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;

View File

@ -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());

View File

@ -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
}

View File

@ -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<String, String> tags = world.getMap().meta.tags;
stream.writeByte(tags.size);
for(Entry<String, String> 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<String, String> 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);

View File

@ -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;
}
}

View File

@ -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));
}
}
}

View File

@ -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();
}
}

View File

@ -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));
}

View File

@ -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;
}
}