diff --git a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java b/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java index a81e3ff27f..5a80dbb4bd 100644 --- a/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java +++ b/core/src/io/anuke/mindustry/content/bullets/TurretBullets.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.math.GridPoint2; import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.content.fx.BulletFx; +import io.anuke.mindustry.content.fx.EnvironmentFx; import io.anuke.mindustry.content.fx.Fx; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; @@ -14,7 +15,9 @@ import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.resource.Liquid; +import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Fill; import io.anuke.ucore.graphics.Lines; @@ -29,6 +32,45 @@ public class TurretBullets { public static final BulletType + fireball = new BulletType(1f, 1) { + { + pierce = true; + hitTiles = false; + drag = 0.3f; + } + + @Override + public void init(Bullet b) { + b.velocity.setLength(0.6f + Mathf.random(2f)); + } + + @Override + public void draw(Bullet b) { + //TODO add color to the bullet + Draw.color(Palette.lightFlame, Palette.darkFlame, Color.GRAY, b.fin()); + Fill.circle(b.x, b.y, 3f * b.fout()); + Draw.reset(); + } + + @Override + public void update(Bullet b) { + if(Mathf.chance(0.04 * Timers.delta())){ + Tile tile = world.tileWorld(b.x, b.y); + if(tile != null){ + Fire.create(tile); + } + } + + if(Mathf.chance(0.1 * Timers.delta())){ + Effects.effect(EnvironmentFx.fireballsmoke, b.x, b.y); + } + + if(Mathf.chance(0.1 * Timers.delta())){ + Effects.effect(EnvironmentFx.ballfire, b.x, b.y); + } + } + }, + basicIron = new BulletType(3f, 5) { @Override public void draw(Bullet b) { diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 86c5ec9d73..8038c3f1cf 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntSet; +import com.badlogic.gdx.utils.reflect.ReflectionException; import io.anuke.mindustry.content.UpgradeRecipes; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.BulletType; @@ -145,6 +146,14 @@ public class NetClient extends Module { } }); + Net.handleClient(InvokePacket.class, packet -> { + try{ + packet.method.invoke(null, packet.args); + }catch (ReflectionException e){ + throw new RuntimeException(e); + } + }); + Net.handleClient(StateSyncPacket.class, packet -> { System.arraycopy(packet.items, 0, state.inventory.writeItems(), 0, packet.items.length); diff --git a/core/src/io/anuke/mindustry/entities/Bullet.java b/core/src/io/anuke/mindustry/entities/Bullet.java index 043052a43e..87d2f84e78 100644 --- a/core/src/io/anuke/mindustry/entities/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/Bullet.java @@ -86,7 +86,7 @@ public class Bullet extends BulletEntity{ public void update(){ super.update(); - if (collidesTiles()) { + if (type.hitTiles && collidesTiles()) { world.raycastEach(world.toTile(lastX), world.toTile(lastY), world.toTile(x), world.toTile(y), (x, y) -> { Tile tile = world.tile(x, y); diff --git a/core/src/io/anuke/mindustry/entities/BulletType.java b/core/src/io/anuke/mindustry/entities/BulletType.java index eac6270104..61e7172ac0 100644 --- a/core/src/io/anuke/mindustry/entities/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/BulletType.java @@ -7,9 +7,11 @@ import io.anuke.ucore.entities.BaseBulletType; public abstract class BulletType extends BaseBulletType{ public float knockback; + public boolean hitTiles = true; public StatusEffect status = StatusEffects.none; public float statusIntensity = 0.5f; + //TODO use float damage public BulletType(float speed, int damage){ this.speed = speed; this.damage = damage; diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/Unit.java index b6f124c2ac..4a0fca1c52 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/Unit.java @@ -78,7 +78,7 @@ public abstract class Unit extends SyncEntity implements SerializableEntity { public Floor getFloorOn(){ Tile tile = world.tileWorld(x, y); - return (Floor)(tile == null || (!(tile.floor() instanceof Floor)) ? Blocks.defaultFloor : tile.floor()); + return (Floor)(tile == null || (tile.floor() == null) ? Blocks.defaultFloor : tile.floor()); } public void updateVelocityStatus(float drag, float maxVelocity){ diff --git a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java index 06bb4fdd4c..3e5bbb331d 100644 --- a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java +++ b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java @@ -4,8 +4,10 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; +import io.anuke.mindustry.content.bullets.TurretBullets; import io.anuke.mindustry.content.fx.ExplosionFx; import io.anuke.mindustry.content.fx.Fx; +import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.Team; @@ -34,10 +36,8 @@ public class DamageArea{ } for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i ++){ - Timers.run(i/2, () -> { - Fireball f = new Fireball(x, y, color, Mathf.random(360f)); - f.add(); - }); + Timers.run(i/2, () -> + Bullet.create(TurretBullets.fireball, null, Team.none, x, y, Mathf.random(360f))); } float e = explosiveness; diff --git a/core/src/io/anuke/mindustry/entities/effect/Fireball.java b/core/src/io/anuke/mindustry/entities/effect/Fireball.java deleted file mode 100644 index 9fa48b1462..0000000000 --- a/core/src/io/anuke/mindustry/entities/effect/Fireball.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.anuke.mindustry.entities.effect; - -import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.content.fx.EnvironmentFx; -import io.anuke.mindustry.graphics.Palette; -import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Effects; -import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.TimedEntity; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.graphics.Fill; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; - -import static io.anuke.mindustry.Vars.effectGroup; -import static io.anuke.mindustry.Vars.world; - -public class Fireball extends TimedEntity { - private float rotation; - private float speed; - private Color color; - - public Fireball(float x, float y, Color color, float rotation){ - set(x, y); - this.rotation = rotation; - this.color = color; - lifetime = 30f + Mathf.random(40f); - speed = 0.6f + Mathf.random(2f); - } - - @Override - public void update() { - super.update(); - - float speed = this.speed * fout(); - x += Angles.trnsx(rotation, speed); - y += Angles.trnsy(rotation, speed); - - if(Mathf.chance(0.04 * Timers.delta())){ - Tile tile = world.tileWorld(x, y); - if(tile != null){ - Fire.create(tile); - } - } - - if(Mathf.chance(0.1 * Timers.delta())){ - Effects.effect(EnvironmentFx.fireballsmoke, x, y); - } - - if(Mathf.chance(0.1 * Timers.delta())){ - Effects.effect(EnvironmentFx.ballfire, x, y); - } - } - - @Override - public void draw() { - Draw.color(Palette.lightFlame, color, Color.GRAY, fin()); - Fill.circle(x, y, 3f * fout()); - Draw.reset(); - } - - @Override - public Fireball add(){ - super.update(); - return add(effectGroup); - } -} diff --git a/core/src/io/anuke/mindustry/entities/effect/Puddle.java b/core/src/io/anuke/mindustry/entities/effect/Puddle.java index 552818ac5b..2249b181c4 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -8,10 +8,13 @@ import com.badlogic.gdx.utils.Pool.Poolable; import com.badlogic.gdx.utils.Pools; import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.content.bullets.TurretBullets; import io.anuke.mindustry.content.fx.BlockFx; import io.anuke.mindustry.content.fx.EnvironmentFx; +import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.SerializableEntity; import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.resource.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects; @@ -105,7 +108,7 @@ public class Puddle extends Entity implements SerializableEntity, Poolable{ (liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid Fire.create(tile); if(Mathf.chance(0.006 * amount)){ - new Fireball(x, y, dest.flameColor, Mathf.random(360f)).add(); + Bullet.create(TurretBullets.fireball, tile.entity, Team.none, x, y, Mathf.random(360f)); } }else if(dest.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot puddle if(Mathf.chance(0.5f * amount)){ diff --git a/core/src/io/anuke/mindustry/net/Invoke.java b/core/src/io/anuke/mindustry/net/Invoke.java index 2a59ec5755..36a0bc7d4e 100644 --- a/core/src/io/anuke/mindustry/net/Invoke.java +++ b/core/src/io/anuke/mindustry/net/Invoke.java @@ -5,32 +5,54 @@ import com.badlogic.gdx.utils.reflect.ClassReflection; import com.badlogic.gdx.utils.reflect.Method; import com.badlogic.gdx.utils.reflect.ReflectionException; import io.anuke.mindustry.Vars; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Packets.InvokePacket; import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.entities.Entities; +import io.anuke.ucore.entities.Entity; import io.anuke.ucore.util.IOUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; +/**Class for invoking static methods of other classes remotely.*/ public class Invoke { private static ObjectMap> methods = new ObjectMap<>(); private static ObjectMap classes = new ObjectMap<>(); + /** + * Invokes a method remotely (on all clients) and locally. + * @param type Type of class to invoke method on + * @param methodName Name of method to invoke. Overloads are not allowed! + * @param args List of arguments to invoke the method with. + */ public static void on(Class type, String methodName, Object... args){ try { Method method = getMethod(type, methodName); + method.invoke(null, args); InvokePacket packet = new InvokePacket(); packet.args = args; packet.type = type; packet.method = method; packet.args = args; Net.send(packet, SendMode.tcp); - method.invoke(null, args); }catch (ReflectionException e){ throw new RuntimeException(e); } } + /** + * Invokes an event in the {@link NetEvents} class by name. + * @param methodName the name of the event method to invoke + * @param args the method arguments + */ + public static void event(String methodName, Object... args){ + on(NetEvents.class, methodName, args); + } + + //TODO refactor to serializer map! static void writeObjects(ByteBuffer buffer, Object[] objects){ for(Object o : objects){ Class type = o.getClass(); @@ -51,6 +73,11 @@ public class Invoke { buffer.putShort((Short)o); }else if(type == Tile.class){ buffer.putInt(((Tile)o).packedPosition()); + }else if(type == Entity.class){ + buffer.put((byte)((Entity)o).getGroup().getID()); + buffer.putInt(((Entity)o).id); + }else if(type == Team.class){ + buffer.put((byte)((Team)o).ordinal()); }else if(type == String.class){ IOUtils.writeString(buffer, (String)o); } @@ -79,6 +106,12 @@ public class Invoke { obj = buffer.getShort(); }else if(type == Tile.class){ obj = Vars.world.tile(buffer.getInt()); + }else if(type == Entity.class){ + byte group = buffer.get(); + int id = buffer.getInt(); + obj = Entities.getGroup(group).getByID(id); + }else if(type == Team.class){ + obj = Team.values()[buffer.get()]; }else if(type == String.class){ obj = IOUtils.readString(buffer); } @@ -113,7 +146,10 @@ public class Invoke { Method method = map.get(methodname); if(method == null){ - method = ClassReflection.getMethod(type, methodname, null); + method = ClassReflection.getMethod(type, methodname, (Class[])null); + if(method.getDeclaredAnnotation(Remote.class) == null){ + throw new RuntimeException("Attempt to invoke method '" + methodname + "', which is not Invokable!"); + } map.put(methodname, method); } @@ -122,4 +158,9 @@ public class Invoke { } + @Retention(RetentionPolicy.RUNTIME) + @interface Remote{ + + } + } diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index d84d98163d..596f22ae8e 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -5,7 +5,6 @@ import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.reflect.ClassReflection; import com.badlogic.gdx.utils.reflect.Method; import com.badlogic.gdx.utils.reflect.ReflectionException; -import com.sun.tools.internal.ws.wsdl.document.Import; import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index 1154b0dcfd..a10bf84e34 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -3,9 +3,10 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import io.anuke.mindustry.content.UnitTypes; +import io.anuke.mindustry.content.bullets.TurretBullets; +import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.effect.Fireball; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.Palette; @@ -59,7 +60,7 @@ public class DebugFragment implements Fragment { row(); new button("effect", () -> { for(int i = 0; i < 20; i ++){ - new Fireball(player.x, player.y, Palette.darkFlame, Mathf.random(360f)).add(); + Bullet.create(TurretBullets.fireball, player, player.team, player.x, player.y, Mathf.random(360f)); } }); row();