diff --git a/core/assets/shaders/hit.fragment b/core/assets/shaders/hit.fragment new file mode 100644 index 0000000000..756f47ef52 --- /dev/null +++ b/core/assets/shaders/hit.fragment @@ -0,0 +1,18 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +uniform sampler2D u_texture; + +varying vec4 v_color; +varying vec2 v_texCoord; + +void main() { + + vec4 c = texture2D(u_texture, v_texCoord.xy); + + c = mix(c, vec4(1.0, 1.0, 1.0, c.a), v_color.a); + + gl_FragColor = c * vec4(v_color.rgb, 1.0); +} diff --git a/core/assets/shaders/outline.fragment b/core/assets/shaders/outline.fragment index c933ab05d9..1c6fdd5b28 100644 --- a/core/assets/shaders/outline.fragment +++ b/core/assets/shaders/outline.fragment @@ -35,9 +35,6 @@ void main() { if(any){ gl_FragColor = u_color; }else{ - if((c.r < 0.01 && c.g < 0.01 && c.b < 0.01)){ - c = vec4(0.0); - } - gl_FragColor = mix(c, vec4(1.0, 1.0, 1.0, c.a), c.a) * v_color; + gl_FragColor = c * v_color; } } diff --git a/core/assets/version.properties b/core/assets/version.properties index 4bc1c15954..0cf82d77cb 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Thu Mar 15 12:56:43 EDT 2018 +#Thu Mar 15 21:41:26 EDT 2018 version=release -androidBuildCode=523 +androidBuildCode=524 name=Mindustry code=3.4 build=custom build diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 7cf55a339e..f2d7ee8eb9 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -158,6 +158,7 @@ public class Control extends Module{ Events.on(ResetEvent.class, () -> { upgrades.reset(); player.weaponLeft = player.weaponRight = Weapon.blaster; + player.team = state.team; player.add(); player.heal(); diff --git a/core/src/io/anuke/mindustry/core/GameState.java b/core/src/io/anuke/mindustry/core/GameState.java index 20acc304e3..7b593ff982 100644 --- a/core/src/io/anuke/mindustry/core/GameState.java +++ b/core/src/io/anuke/mindustry/core/GameState.java @@ -1,9 +1,11 @@ package io.anuke.mindustry.core; +import com.badlogic.gdx.utils.ObjectSet; import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.Inventory; +import io.anuke.mindustry.game.Team; import io.anuke.ucore.core.Events; public class GameState{ @@ -20,6 +22,9 @@ public class GameState{ public GameMode mode = GameMode.waves; public Difficulty difficulty = Difficulty.normal; public boolean friendlyFire; + public Team team = Team.none; //the team that the player is on + public ObjectSet enemyTeams = new ObjectSet<>(), //enemies to the player team + allyTeams = new ObjectSet<>(); //allies to the player team public void set(State astate){ Events.fire(StateChangeEvent.class, state, astate); diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 096be6e247..17058fb7d8 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -7,6 +7,7 @@ import io.anuke.mindustry.game.EventType.GameOverEvent; import io.anuke.mindustry.game.EventType.PlayEvent; import io.anuke.mindustry.game.EventType.ResetEvent; import io.anuke.mindustry.game.EventType.WaveEvent; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.WaveCreator; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; @@ -53,6 +54,10 @@ public class Logic extends Module { state.lastUpdated = -1; state.gameOver = false; state.inventory.clearItems(); + state.allyTeams.clear(); + state.enemyTeams.clear(); + state.enemyTeams.add(Team.red); + state.team = Team.none; Timers.clear(); Entities.clear(); diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 52981d04e8..2b87c2b9d0 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntSet; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; @@ -22,7 +21,6 @@ import io.anuke.mindustry.world.blocks.ProductionBlocks; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.BaseBulletType; import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.modules.Module; import io.anuke.ucore.util.Log; @@ -33,15 +31,20 @@ import java.nio.ByteBuffer; import static io.anuke.mindustry.Vars.*; public class NetClient extends Module { - private final static float dataTimeout = 60*18; //18 seconds timeout + private final static float dataTimeout = 60*18; private final static float playerSyncTime = 2; private Timer timer = new Timer(5); + /**Whether the client is currently conencting.*/ private boolean connecting = false; - private boolean kicked = false; + /**If true, no message will be shown on disconnect.*/ + private boolean quiet = false; + /**List of all recieved entitity IDs, to prevent duplicates.*/ private IntSet recieved = new IntSet(); - private IntMap recent = new IntMap<>(); - private float timeoutTime = 0f; //data timeout counter + /**List of recently recieved entities that have not been added to the queue yet.*/ + private IntMap recent = new IntMap<>(); + /**Counter for data timeout.*/ + private float timeoutTime = 0f; public NetClient(){ @@ -53,7 +56,7 @@ public class NetClient extends Module { recent.clear(); timeoutTime = 0f; connecting = true; - kicked = false; + quiet = false; ui.chatfrag.clearMessages(); ui.loadfrag.hide(); @@ -78,7 +81,7 @@ public class NetClient extends Module { }); Net.handleClient(Disconnect.class, packet -> { - if (kicked) return; + if (quiet) return; Timers.runTask(3f, ui.loadfrag::hide); @@ -187,23 +190,29 @@ public class NetClient extends Module { Log.info("Recieved entity {0}", packet.entity.id); }); - Net.handleClient(EnemyDeathPacket.class, packet -> { - BaseUnit enemy = enemyGroup.getByID(packet.id); - if (enemy != null){ - enemy.type.onDeath(enemy, true); - }else if(recent.get(packet.id) != null){ - recent.get(packet.id).remove(); - }else{ - Log.err("Got remove for null entity! {0}", packet.id); - } + Net.handleClient(EntityDeathPacket.class, packet -> { + EntityGroup group = Entities.getGroup(packet.group); + SyncEntity entity = (SyncEntity) group.getByID(packet.id); + recieved.add(packet.id); + + if(entity != null) { + entity.onRemoteDeath(); + }else{ + if(recent.get(packet.id) != null){ + recent.get(packet.id).onRemoteDeath(); + }else{ + Log.err("Got remove for null entity! {0} / group type {1}", packet.id, group.getType()); + } + } }); - Net.handleClient(BulletPacket.class, packet -> { - //TODO shoot effects for enemies, clientside as well as serverside - BulletType type = (BulletType) BaseBulletType.getByID(packet.type); - Entity owner = enemyGroup.getByID(packet.owner); - new Bullet(type, owner, packet.x, packet.y, packet.angle).add(); + Net.handleClient(EntityShootPacket.class, packet -> { + BulletType type = BaseBulletType.getByID(packet.bulletid); + EntityGroup group = Entities.getGroup(packet.groupid); + SyncEntity owner = (SyncEntity) group.getByID(packet.entityid); + + owner.onRemoteShoot(type, packet.x, packet.y, packet.rotation, packet.data); }); Net.handleClient(BlockDestroyPacket.class, packet -> { @@ -231,7 +240,7 @@ public class NetClient extends Module { }); Net.handleClient(KickPacket.class, packet -> { - kicked = true; + quiet = true; Net.disconnect(); state.set(State.menu); if(!packet.reason.quiet) ui.showError("$text.server.kicked." + packet.reason.name()); @@ -243,7 +252,7 @@ public class NetClient extends Module { world.getCore().entity != null){ world.getCore().entity.onDeath(true); } - kicked = true; + quiet = true; ui.restart.show(); }); @@ -279,7 +288,7 @@ public class NetClient extends Module { if(timeoutTime > dataTimeout){ Log.err("Failed to load data!"); ui.loadfrag.hide(); - kicked = true; + quiet = true; ui.showError("$text.disconnect.data"); Net.disconnect(); timeoutTime = 0f; @@ -306,7 +315,7 @@ public class NetClient extends Module { } public void disconnectQuietly(){ - kicked = true; + quiet = true; Net.disconnect(); } diff --git a/core/src/io/anuke/mindustry/core/NetCommon.java b/core/src/io/anuke/mindustry/core/NetCommon.java index 9b8a9435da..585e5485e5 100644 --- a/core/src/io/anuke/mindustry/core/NetCommon.java +++ b/core/src/io/anuke/mindustry/core/NetCommon.java @@ -3,9 +3,11 @@ package io.anuke.mindustry.core; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; -import io.anuke.mindustry.net.Packets.*; +import io.anuke.mindustry.net.Packets.BlockConfigPacket; +import io.anuke.mindustry.net.Packets.BlockTapPacket; +import io.anuke.mindustry.net.Packets.ChatPacket; +import io.anuke.mindustry.net.Packets.WeaponSwitchPacket; import io.anuke.mindustry.resource.Upgrade; -import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.modules.Module; @@ -15,13 +17,6 @@ public class NetCommon extends Module { public NetCommon(){ - Net.handle(ShootPacket.class, (packet) -> { - Player player = playerGroup.getByID(packet.playerid); - - Weapon weapon = (Weapon) Upgrade.getByID(packet.weaponid); - weapon.shoot(player, packet.x, packet.y, packet.rotation); - }); - Net.handle(ChatPacket.class, (packet) -> { ui.chatfrag.addMessage(packet.text, colorizeName(packet.id, packet.name)); }); @@ -31,8 +26,8 @@ public class NetCommon extends Module { if (player == null) return; - player.weaponLeft = (Weapon) Upgrade.getByID(packet.left); - player.weaponRight = (Weapon) Upgrade.getByID(packet.right); + player.weaponLeft = Upgrade.getByID(packet.left); + player.weaponRight = Upgrade.getByID(packet.right); }); Net.handle(BlockTapPacket.class, (packet) -> { @@ -44,13 +39,6 @@ public class NetCommon extends Module { Tile tile = world.tile(packet.position); if (tile != null) tile.block().configure(tile, packet.data); }); - - Net.handle(PlayerDeathPacket.class, (packet) -> { - Player player = playerGroup.getByID(packet.id); - if(player == null) return; - - player.doRespawn(); - }); } public void sendMessage(String message){ diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 3d9678243c..28ce107f4b 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.core; import com.badlogic.gdx.utils.*; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.game.EventType.GameOverEvent; @@ -17,6 +18,7 @@ import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Placement; import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.entities.BaseBulletType; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.modules.Module; @@ -157,8 +159,15 @@ public class NetServer extends Module{ //...don't do anything here as it's already handled by the packet itself }); - Net.handleServer(ShootPacket.class, (id, packet) -> { - packet.playerid = connections.get(id).id; + Net.handleServer(EntityShootPacket.class, (id, packet) -> { + Player player = connections.get(id); + + BulletType type = BaseBulletType.getByID(packet.bulletid); + + player.onRemoteShoot(type, packet.x, packet.y, packet.rotation, packet.data); + + packet.entityid = player.id; + packet.groupid = (byte)player.getGroup().getID(); Net.sendExcept(id, packet, SendMode.udp); }); @@ -201,7 +210,7 @@ public class NetServer extends Module{ }); Net.handleServer(ChatPacket.class, (id, packet) -> { - if(!Timers.get("chatFlood" + id, 20)){ + if(!Timers.get("chatFlood" + id, 30)){ ChatPacket warn = new ChatPacket(); warn.text = "[scarlet]You are sending messages too quickly."; Net.sendTo(id, warn, SendMode.tcp); @@ -249,8 +258,9 @@ public class NetServer extends Module{ } }); - Net.handleServer(PlayerDeathPacket.class, (id, packet) -> { + Net.handleServer(EntityDeathPacket.class, (id, packet) -> { packet.id = connections.get(id).id; + packet.group = (byte)connections.get(id).getGroup().getID(); Net.sendExcept(id, packet, SendMode.tcp); }); diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 4a554a3fd8..97ac9f0fbf 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -217,7 +217,9 @@ public class Renderer extends RendererModule{ Shaders.outline.color.set(team.color); Graphics.beginShaders(Shaders.outline); + //Graphics.shader(Shaders.hit); drawTeam(team, flying); + //Graphics.shader(); Graphics.endShaders(); } } diff --git a/core/src/io/anuke/mindustry/entities/Bullet.java b/core/src/io/anuke/mindustry/entities/Bullet.java index cfc1b38664..37bcdc6e9c 100644 --- a/core/src/io/anuke/mindustry/entities/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/Bullet.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.entities; import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.entities.BulletEntity; import io.anuke.ucore.entities.Entity; @@ -39,6 +40,10 @@ public class Bullet extends BulletEntity{ public boolean collidesTiles(){ return owner instanceof BaseUnit; } + + public Team team(){ + return ((Unit)owner).team; + } @Override public void update(){ diff --git a/core/src/io/anuke/mindustry/entities/BulletType.java b/core/src/io/anuke/mindustry/entities/BulletType.java index 9048de86e5..1f74ab18ce 100644 --- a/core/src/io/anuke/mindustry/entities/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/BulletType.java @@ -3,12 +3,11 @@ package io.anuke.mindustry.entities; import com.badlogic.gdx.graphics.Color; import io.anuke.mindustry.entities.effect.DamageArea; import io.anuke.mindustry.entities.effect.EMP; -import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.graphics.Fx; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.BaseBulletType; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; @@ -122,7 +121,7 @@ public abstract class BulletType extends BaseBulletType{ Effects.effect(Fx.shellsmoke, b); Effects.effect(Fx.shellexplosion, b); - DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 25f, (int)(damage * 2f/3f)); + DamageArea.damage(b.team(), b.x, b.y, 25f, (int)(damage * 2f/3f)); } }, flak = new BulletType(2.9f, 8) { @@ -202,7 +201,7 @@ public abstract class BulletType extends BaseBulletType{ Effects.effect(Fx.shellsmoke, b); Effects.effect(Fx.shockwaveSmall, b); - DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 50f, (int)(damage * 2f/3f)); + DamageArea.damage(b.team(), b.x, b.y, 50f, (int)(damage * 2f/3f)); } }, yellowshell = new BulletType(1.2f, 20){ @@ -233,7 +232,7 @@ public abstract class BulletType extends BaseBulletType{ Effects.effect(Fx.shellsmoke, b); Effects.effect(Fx.shockwaveSmall, b); - DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 25f, (int)(damage * 2f/3f)); + DamageArea.damage(b.team(), b.x, b.y, 25f, (int)(damage * 2f/3f)); } }, blast = new BulletType(1.1f, 90){ @@ -371,7 +370,7 @@ public abstract class BulletType extends BaseBulletType{ Effects.effect(Fx.clusterbomb, b); - DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 35f, damage); + DamageArea.damage(b.team(), b.x, b.y, 35f, damage); } }, vulcan = new BulletType(4.5f, 12) { @@ -450,7 +449,7 @@ public abstract class BulletType extends BaseBulletType{ } public void init(Bullet b) { - DamageArea.damageLine(b.owner, Fx.beamhit, b.x, b.y, b.angle(), length, damage); + DamageArea.damageLine(b.team(), Fx.beamhit, b.x, b.y, b.angle(), length, damage); } public void draw(Bullet b) { diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 6bfe36f122..9f4982cee6 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -57,6 +57,13 @@ public class Player extends Unit{ heal(); } + @Override + public void onRemoteShoot(BulletType type, float x, float y, float rotation, short data) { + //TODO shoot! + Weapon weapon = Upgrade.getByID((byte)data); + weapon.shoot(player, x, y, rotation); + } + @Override public float getMass(){ return mech.mass; @@ -105,8 +112,8 @@ public class Player extends Unit{ ui.hudfrag.fadeRespawn(true); } - /**called when a remote player death event is recieved*/ - public void doRespawn(){ + @Override + public void onRemoteDeath(){ dead = true; Effects.effect(Fx.explosion, this); Effects.shake(4f, 5f, this); @@ -136,7 +143,7 @@ public class Player extends Unit{ float ft = Mathf.sin(walktime, 6f, 2f); - Draw.alpha(hitTime / hitDuration); + //Draw.alpha(hitTime / hitDuration); for(int i : Mathf.signs){ tr.trns(footRotation, ft * i); @@ -154,7 +161,7 @@ public class Player extends Unit{ Draw.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, rotation - 90); } - Draw.alpha(1f); + //Draw.alpha(1f); x = px; y = py; diff --git a/core/src/io/anuke/mindustry/entities/SyncEntity.java b/core/src/io/anuke/mindustry/entities/SyncEntity.java index 17b51a8fee..dcf5219dd5 100644 --- a/core/src/io/anuke/mindustry/entities/SyncEntity.java +++ b/core/src/io/anuke/mindustry/entities/SyncEntity.java @@ -14,15 +14,24 @@ import static io.anuke.mindustry.Vars.threads; /**Base class for any entity that needs to be synced across clients.*/ public abstract class SyncEntity extends DestructibleEntity{ - protected transient Interpolator interpolator = new Interpolator(); + /**Interpolator, used for smoothing position.*/ + protected Interpolator interpolator = new Interpolator(); /**smoothed position and rotation*/ private Vector3 spos = new Vector3(); /**the general rotation.*/ public float rotation; + /**Called when a death event is recieved remotely.*/ + public abstract void onRemoteDeath(); + + /**Called when a shoot event is recieved remotely.*/ + public abstract void onRemoteShoot(BulletType type, float x, float y, float rotation, short data); + + //Read and write spawn data, which is sent when the entity is requested public abstract void writeSpawn(ByteBuffer data); public abstract void readSpawn(ByteBuffer data); + //Read and write sync data, usually position public abstract void write(ByteBuffer data); public abstract void read(ByteBuffer data, long time); @@ -101,6 +110,7 @@ public abstract class SyncEntity extends DestructibleEntity{ } public void update(){ + //TODO prevent rubberbanding from getting too bad, clamp values? time += 1f / spacing * Math.min(Timers.delta(), 1f); diff --git a/core/src/io/anuke/mindustry/entities/Units.java b/core/src/io/anuke/mindustry/entities/Units.java index be45666659..f5348d57a0 100644 --- a/core/src/io/anuke/mindustry/entities/Units.java +++ b/core/src/io/anuke/mindustry/entities/Units.java @@ -1,18 +1,24 @@ package io.anuke.mindustry.entities; import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.ObjectSet; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.game.Team; +import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.function.Consumer; +import io.anuke.ucore.function.Predicate; -import static io.anuke.mindustry.Vars.playerGroup; -import static io.anuke.mindustry.Vars.unitGroups; +import static io.anuke.mindustry.Vars.*; -/**Utility class for unit-based interactions.*/ +/**Utility class for unit and team interactions.*/ public class Units { + private static Rectangle rect = new Rectangle(); + /**Iterates over all units on all teams, including players.*/ public static void allUnits(Consumer cons){ + //check all unit groups first for(EntityGroup group : unitGroups){ if(!group.isEmpty()){ for(BaseUnit unit : group.all()){ @@ -21,12 +27,73 @@ public class Units { } } + //then check all player groups for(Player player : playerGroup.all()){ cons.accept(player); } } - public static void getNearbyEnemies(Team team, Rectangle rect, Consumer cons){ + public static Unit getClosestEnemies(Team team, float x, float y, float range, Predicate predicate){ + Unit[] result = {null}; + float[] cdist = {0}; + getNearbyEnemies(team, rect, e -> { + if (!predicate.test(e)) + return; + + float dist = Vector2.dst(e.x, e.y, x, y); + if (dist < range) { + if (result[0] == null || dist < cdist[0]) { + result[0] = e; + cdist[0] = dist; + } + } + }); + + return result[0]; + } + + /**Iterates over all units in a rectangle.*/ + public static void getNearby(Rectangle rect, Consumer cons){ + + for(Team team : Team.values()){ + EntityGroup group = unitGroups[team.ordinal()]; + if(!group.isEmpty()){ + Entities.getNearby(group, rect, entity -> cons.accept((Unit)entity)); + } + } + + //now check all enemy players + Entities.getNearby(playerGroup, rect, player -> cons.accept((Unit)player)); + } + + /**Iterates over all units that are enemies of this team.*/ + public static void getNearbyEnemies(Team team, Rectangle rect, Consumer cons){ + //check if it's an ally team to the 'main team' + boolean ally = state.team == team || state.allyTeams.contains(team); + + ObjectSet targets = ally ? state.enemyTeams : state.allyTeams; + + for(Team other : targets){ + EntityGroup group = unitGroups[other.ordinal()]; + if(!group.isEmpty()){ + Entities.getNearby(group, rect, entity -> cons.accept((Unit)entity)); + } + } + + //now check all enemy players + Entities.getNearby(playerGroup, rect, player -> { + if(targets.contains(((Player)player).team)){ + cons.accept((Unit)player); + } + }); + } + + /**Returns whether these two teams are enemies.*/ + public static boolean areEnemies(Team team, Team other){ + if(team == other) return false; //fast fail to be more efficient + boolean ally = state.team == team || state.allyTeams.contains(team); + boolean ally2 = state.team == other || state.allyTeams.contains(other); + return ally == ally2; } } diff --git a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java index d58ba9727a..e3c5e2a225 100644 --- a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java +++ b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java @@ -2,27 +2,27 @@ package io.anuke.mindustry.entities.effect; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; -import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.entities.DestructibleEntity; -import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.Entity; -import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Physics; import io.anuke.ucore.util.Translator; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.world; public class DamageArea{ private static Rectangle rect = new Rectangle(); private static Translator tr = new Translator(); - //only for entities, not tiles (yet!) - public static void damageLine(Entity owner, Effect effect, float x, float y, float angle, float length, int damage){ + /**Damages entities in a line. + * Only enemies of the specified team are damaged.*/ + public static void damageLine(Team team, Effect effect, float x, float y, float angle, float length, int damage){ tr.trns(angle, length); rect.setPosition(x, y).setSize(tr.x, tr.y); float x2 = tr.x + x, y2 = tr.y + y; @@ -44,10 +44,8 @@ public class DamageArea{ rect.width += expand*2; rect.height += expand*2; - Consumer cons = e -> { - if(e == owner) return; - DestructibleEntity enemy = (DestructibleEntity) e; - Rectangle other = enemy.hitbox.getRect(enemy.x, enemy.y); + Consumer cons = e -> { + Rectangle other = e.hitbox.getRect(e.x, e.y); other.y -= expand; other.x -= expand; other.width += expand * 2; @@ -57,53 +55,49 @@ public class DamageArea{ if (vec != null) { Effects.effect(effect, vec.x, vec.y); - enemy.damage(damage); + e.damage(damage); } }; - Entities.getNearby(enemyGroup, rect, cons); - if(state.friendlyFire) Entities.getNearby(playerGroup, rect, cons); + Units.getNearbyEnemies(team, rect, cons); } - - public static void damageEntities(float x, float y, float radius, int damage){ - damage(true, x, y, radius, damage); - for(Player player : playerGroup.all()){ - //if(player.isAndroid) continue; - int amount = calculateDamage(x, y, player.x, player.y, radius, damage); - player.damage(amount); - } + /**Damages everything in a radius.*/ + public static void damage(float x, float y, float radius, int damage){ + damage(null, x, y, radius, damage); } - - public static void damage(boolean enemies, float x, float y, float radius, int damage){ - Consumer cons = entity -> { - DestructibleEntity enemy = (DestructibleEntity)entity; - if(enemy.distanceTo(x, y) > radius){ + + /**Damages all entities and blocks in a radius that are enemies of the team.*/ + public static void damage(Team team, float x, float y, float radius, int damage){ + Consumer cons = entity -> { + if(entity.distanceTo(x, y) > radius){ return; } - int amount = calculateDamage(x, y, enemy.x, enemy.y, radius, damage); - enemy.damage(amount); + int amount = calculateDamage(x, y, entity.x, entity.y, radius, damage); + entity.damage(amount); }; - - if(enemies){ - Entities.getNearby(enemyGroup, x, y, radius*2, cons); + + rect.setSize(radius *2).setCenter(x, y); + if(team != null) { + Units.getNearbyEnemies(team, rect, cons); }else{ - int trad = (int)(radius / tilesize); - for(int dx = -trad; dx <= trad; dx ++){ - for(int dy= -trad; dy <= trad; dy ++){ - Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy); - if(tile != null && tile.entity != null && Vector2.dst(dx, dy, 0, 0) <= trad){ - int amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage); - tile.entity.damage(amount); - } + Units.getNearby(rect, cons); + } + + int trad = (int)(radius / tilesize); + for(int dx = -trad; dx <= trad; dx ++){ + for(int dy= -trad; dy <= trad; dy ++){ + Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy); + if(tile != null && tile.entity != null && (team == null || Units.areEnemies(team, tile.getTeam())) && Vector2.dst(dx, dy, 0, 0) <= trad){ + int amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage); + tile.entity.damage(amount); } } - - Entities.getNearby(playerGroup, x, y, radius*2, cons); } + } - static int calculateDamage(float x, float y, float tx, float ty, float radius, int damage){ + private static int calculateDamage(float x, float y, float tx, float ty, float radius, int damage){ float dist = Vector2.dst(x, y, tx, ty); float scaled = 1f - dist/radius; return (int)(damage * scaled); diff --git a/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java b/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java index 0178342027..8ad021d36e 100644 --- a/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java +++ b/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java @@ -1,40 +1,45 @@ package io.anuke.mindustry.entities.effect; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectSet; +import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.Fx; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entity; -import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.enemyGroup; - public class TeslaOrb extends Entity{ - private Array points = new Array<>(); - private ObjectSet hit = new ObjectSet<>(); - private int damage = 0; - private float range = 0; - private float lifetime = 30f; + private final static Rectangle rect = new Rectangle(); + + private final Array points = new Array<>(); + private final ObjectSet hit = new ObjectSet<>(); + private final int damage; + private final float range; + private final float lifetime = 30f; + private final Vector2 vector = new Vector2(); + private final Team team; + private float life = 0f; - private Vector2 vector = new Vector2(); + private float curx = x, cury = y; + private boolean done = false; - public TeslaOrb(float x, float y, float range, int damage){ + public TeslaOrb(Team team, float x, float y, float range, int damage){ set(x, y); + this.team = team; this.damage = damage; this.range = range; } void shock(){ float stopchance = 0.1f; - float curx = x, cury = y; float shake = 3f; int max = 7; @@ -43,19 +48,19 @@ public class TeslaOrb extends Entity{ if(Mathf.chance(stopchance)){ break; } - - Array enemies = Entities.getNearby(enemyGroup, curx, cury, range*2f); - - for(SolidEntity entity : enemies){ - if(entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((BaseUnit)entity)){ + + rect.setSize(range*2f).setCenter(curx, cury); + + Units.getNearbyEnemies(team, rect, entity -> { + if(!done && entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((BaseUnit)entity)){ hit.add((BaseUnit)entity); points.add(new Vector2(entity.x + Mathf.range(shake), entity.y + Mathf.range(shake))); damageEnemy((BaseUnit)entity); curx = entity.x; cury = entity.y; - break; + done = true; } - } + }); } if(points.size == 0){ @@ -107,11 +112,6 @@ public class TeslaOrb extends Entity{ Draw.rect("circle", x, y, rad, rad); } - //Draw.color(Color.WHITE); - - //Draw.stroke(2f - life/lifetime*2f); - //Draw.line(x1, y1, x2, y2); - Draw.reset(); previous = enemy; diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index 571e38a070..f26454b94d 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.entities.units; import io.anuke.mindustry.entities.Bullet; +import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Unit; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.SolidEntity; @@ -63,9 +64,19 @@ public class BaseUnit extends Unit { hitTime = hitDuration; } + @Override + public void onRemoteShoot(BulletType type, float x, float y, float rotation, short data) { + new Bullet(type, this, x, y, rotation).add().damage = data; + } + @Override public void onDeath(){ - type.onDeath(this, false); + type.onDeath(this); + } + + @Override + public void onRemoteDeath(){ + type.onRemoteDeath(this); } @Override diff --git a/core/src/io/anuke/mindustry/entities/units/UnitType.java b/core/src/io/anuke/mindustry/entities/units/UnitType.java index 28f4c8b95d..ba9cee45e3 100644 --- a/core/src/io/anuke/mindustry/entities/units/UnitType.java +++ b/core/src/io/anuke/mindustry/entities/units/UnitType.java @@ -67,7 +67,11 @@ public class UnitType { //TODO } - public void onDeath(BaseUnit enemy, boolean force){ + public void onDeath(BaseUnit enemy){ + //TODO + } + + public void onRemoteDeath(BaseUnit enemy){ //TODO } diff --git a/core/src/io/anuke/mindustry/game/Team.java b/core/src/io/anuke/mindustry/game/Team.java index dbe4a0c78f..f16c48b30a 100644 --- a/core/src/io/anuke/mindustry/game/Team.java +++ b/core/src/io/anuke/mindustry/game/Team.java @@ -3,7 +3,7 @@ package io.anuke.mindustry.game; import com.badlogic.gdx.graphics.Color; public enum Team { - none(Color.GRAY), + none(Color.DARK_GRAY), blue(Color.BLUE), red(Color.RED); diff --git a/core/src/io/anuke/mindustry/graphics/Shaders.java b/core/src/io/anuke/mindustry/graphics/Shaders.java index bd7f1a668a..915d725100 100644 --- a/core/src/io/anuke/mindustry/graphics/Shaders.java +++ b/core/src/io/anuke/mindustry/graphics/Shaders.java @@ -15,6 +15,7 @@ public class Shaders{ public static final SurfaceShader water = new SurfaceShader("water"); public static final SurfaceShader lava = new SurfaceShader("lava"); public static final SurfaceShader oil = new SurfaceShader("oil"); + public static final Shader hit = new Shader("hit", "default") { protected void apply() {}}; private static final Vector2 vec = new Vector2(); diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save16.java index 98b25a20cb..de0084ad3e 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save16.java @@ -6,6 +6,7 @@ import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.GameMode; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.io.SaveMeta; import io.anuke.mindustry.resource.Item; @@ -18,7 +19,7 @@ import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.types.BlockPart; import io.anuke.mindustry.world.blocks.types.Rock; import io.anuke.ucore.core.Core; -import io.anuke.ucore.entities.EntityGroup.EntityContainer; +import io.anuke.ucore.entities.EntityGroup; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -84,7 +85,6 @@ public class Save16 extends SaveFileVersion { Core.camera.position.set(playerx, playery, 0); //weapons - control.upgrades().getWeapons().clear(); control.upgrades().getWeapons().add(Weapon.blaster); player.weaponLeft = player.weaponRight = Weapon.blaster; @@ -117,26 +117,28 @@ public class Save16 extends SaveFileVersion { //enemies - int enemies = stream.readInt(); + byte teams = stream.readByte(); - for(int i = 0; i < enemies; i ++){ - byte type = stream.readByte(); - float x = stream.readFloat(); - float y = stream.readFloat(); - int health = stream.readShort(); + for(int i = 0; i < teams; i ++){ + EntityGroup group = unitGroups[i]; + + int amount = stream.readInt(); + + for(int j = 0; j < amount; j ++){ + byte type = stream.readByte(); + float x = stream.readFloat(); + float y = stream.readFloat(); + int health = stream.readShort(); - try{ BaseUnit enemy = new BaseUnit(UnitType.getByID(type)); enemy.health = health; enemy.x = x; enemy.y = y; - enemy.add(enemyGroup); - }catch (Exception e){ - throw new RuntimeException(e); + enemy.add(group); } } - state.enemies = enemies; + state.enemies = 0; //TODO display enemies correctly! state.wave = wave; state.wavetime = wavetime; @@ -186,9 +188,11 @@ public class Save16 extends SaveFileVersion { } if(tile.entity != null){ + byte team = stream.readByte(); byte rotation = stream.readByte(); short health = stream.readShort(); + tile.setTeam(Team.values()[team]); tile.entity.health = health; tile.setRotation(rotation); @@ -265,17 +269,18 @@ public class Save16 extends SaveFileVersion { } //--ENEMIES-- + stream.writeByte(Team.values().length); //amount of total teams (backwards compatibility) - EntityContainer enemies = enemyGroup.all(); + for(Team team : Team.values()){ + EntityGroup group = unitGroups[team.ordinal()]; + stream.writeInt(group.size()); //amount of units in the team group - stream.writeInt(enemies.size()); //enemy amount - - for(int i = 0; i < enemies.size(); i ++){ - BaseUnit enemy = enemies.get(i); - stream.writeByte(enemy.type.id); //type - stream.writeFloat(enemy.x); //x - stream.writeFloat(enemy.y); //y - stream.writeShort(enemy.health); //health + for(BaseUnit unit : group.all()){ + stream.writeByte(unit.type.id); //type + stream.writeFloat(unit.x); //x + stream.writeFloat(unit.y); //y + stream.writeShort(unit.health); //health + } } //--MAP DATA-- @@ -329,6 +334,7 @@ public class Save16 extends SaveFileVersion { if(tile.block() instanceof BlockPart) stream.writeByte(tile.link); if(tile.entity != null){ + stream.writeByte(tile.getTeam().ordinal()); stream.writeByte(tile.getRotation()); //rotation stream.writeShort((short)tile.entity.health); //health diff --git a/core/src/io/anuke/mindustry/net/NetEvents.java b/core/src/io/anuke/mindustry/net/NetEvents.java index f3cf3b2204..8b35586b76 100644 --- a/core/src/io/anuke/mindustry/net/NetEvents.java +++ b/core/src/io/anuke/mindustry/net/NetEvents.java @@ -1,16 +1,15 @@ package io.anuke.mindustry.net; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.entities.Entity; import static io.anuke.mindustry.Vars.*; @@ -29,20 +28,11 @@ public class NetEvents { Net.send(new GameOverPacket(), SendMode.tcp); } - public static void handleBullet(BulletType type, Entity owner, float x, float y, float angle, short damage){ - BulletPacket packet = new BulletPacket(); - packet.x = x; - packet.y = y; - packet.angle = angle; - packet.damage = damage; - packet.owner = owner.id; - packet.type = type.id; - Net.send(packet, SendMode.udp); - } - public static void handleEnemyDeath(BaseUnit enemy){ - EnemyDeathPacket packet = new EnemyDeathPacket(); + public static void handleUnitDeath(Unit enemy){ + EntityDeathPacket packet = new EntityDeathPacket(); packet.id = enemy.id; + packet.group = (byte)enemy.getGroup().getID(); Net.send(packet, SendMode.tcp); } @@ -60,7 +50,7 @@ public class NetEvents { } public static void handlePlayerDeath(){ - PlayerDeathPacket packet = new PlayerDeathPacket(); + EntityDeathPacket packet = new EntityDeathPacket(); packet.id = Vars.player.id; Net.send(packet, SendMode.tcp); } @@ -100,13 +90,14 @@ public class NetEvents { Net.send(packet, SendMode.tcp); } - public static void handleShoot(Weapon weapon, float x, float y, float angle){ - ShootPacket packet = new ShootPacket(); - packet.weaponid = weapon.id; + public static void handleShoot(SyncEntity entity, float x, float y, float angle, short data){ + EntityShootPacket packet = new EntityShootPacket(); + packet.groupid = (byte)entity.getGroup().getID(); packet.x = x; packet.y = y; + packet.data = data; packet.rotation = angle; - packet.playerid = Vars.player.id; + packet.entityid = entity.id; Net.send(packet, SendMode.udp); } diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index ea8b387946..4dad5587e3 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -161,60 +161,31 @@ public class Packets { } } - //not a real packet. - public static class EffectPacket{ - public int id; + public static class EntityShootPacket implements Packet{ public float x, y, rotation; - public int color; - } - - public static class ShootPacket implements Packet{ - public byte weaponid; - public float x, y, rotation; - public int playerid; + public short bulletid; + public byte groupid; + public short data; + public int entityid; @Override public void write(ByteBuffer buffer) { - buffer.put(weaponid); + buffer.put(groupid); + buffer.putInt(entityid); buffer.putFloat(x); buffer.putFloat(y); buffer.putFloat(rotation); - buffer.putInt(playerid); + buffer.putShort(bulletid); } @Override public void read(ByteBuffer buffer) { - weaponid = buffer.get(); + groupid = buffer.get(); + entityid = buffer.getInt(); x = buffer.getFloat(); y = buffer.getFloat(); rotation = buffer.getFloat(); - playerid = buffer.getInt(); - } - } - - public static class BulletPacket implements Packet{ - public int type, owner; - public float x, y, angle; - public short damage; - - @Override - public void write(ByteBuffer buffer) { - buffer.putShort((short)type); - buffer.putInt(owner); - buffer.putFloat(x); - buffer.putFloat(y); - buffer.putFloat(angle); - buffer.putShort(damage); - } - - @Override - public void read(ByteBuffer buffer) { - type = buffer.getShort(); - owner = buffer.getInt(); - x = buffer.getFloat(); - y = buffer.getFloat(); - angle = buffer.getFloat(); - damage = buffer.getShort(); + bulletid = buffer.getShort(); } } @@ -289,16 +260,19 @@ public class Packets { } } - public static class EnemyDeathPacket implements Packet{ + public static class EntityDeathPacket implements Packet{ + public byte group; public int id; @Override public void write(ByteBuffer buffer) { + buffer.put(group); buffer.putInt(id); } @Override public void read(ByteBuffer buffer) { + group = buffer.get(); id = buffer.getInt(); } } @@ -496,20 +470,6 @@ public class Packets { } } - public static class PlayerDeathPacket implements Packet{ - public int id; - - @Override - public void write(ByteBuffer buffer) { - buffer.putInt(id); - } - - @Override - public void read(ByteBuffer buffer) { - id = buffer.getInt(); - } - } - public static class CustomMapPacket extends Streamable{ } diff --git a/core/src/io/anuke/mindustry/net/Registrator.java b/core/src/io/anuke/mindustry/net/Registrator.java index 12e6c554c1..a1ec2465e2 100644 --- a/core/src/io/anuke/mindustry/net/Registrator.java +++ b/core/src/io/anuke/mindustry/net/Registrator.java @@ -8,40 +8,38 @@ import io.anuke.mindustry.net.Streamable.StreamChunk; public class Registrator { private static Class[] classes = { - StreamBegin.class, - StreamChunk.class, - WorldData.class, - SyncPacket.class, - PositionPacket.class, - ShootPacket.class, - PlacePacket.class, - BreakPacket.class, - StateSyncPacket.class, - BlockSyncPacket.class, - BulletPacket.class, - EnemyDeathPacket.class, - BlockUpdatePacket.class, - BlockDestroyPacket.class, - ConnectPacket.class, - DisconnectPacket.class, - ChatPacket.class, - KickPacket.class, - UpgradePacket.class, - WeaponSwitchPacket.class, - BlockTapPacket.class, - BlockConfigPacket.class, - EntityRequestPacket.class, - ConnectConfirmPacket.class, - GameOverPacket.class, - FriendlyFireChangePacket.class, - PlayerDeathPacket.class, - CustomMapPacket.class, - MapAckPacket.class, - EntitySpawnPacket.class, - NetErrorPacket.class, - PlayerAdminPacket.class, - AdministerRequestPacket.class, - TracePacket.class, + StreamBegin.class, + StreamChunk.class, + WorldData.class, + SyncPacket.class, + PositionPacket.class, + EntityShootPacket.class, + PlacePacket.class, + BreakPacket.class, + StateSyncPacket.class, + BlockSyncPacket.class, + EntityDeathPacket.class, + BlockUpdatePacket.class, + BlockDestroyPacket.class, + ConnectPacket.class, + DisconnectPacket.class, + ChatPacket.class, + KickPacket.class, + UpgradePacket.class, + WeaponSwitchPacket.class, + BlockTapPacket.class, + BlockConfigPacket.class, + EntityRequestPacket.class, + ConnectConfirmPacket.class, + GameOverPacket.class, + FriendlyFireChangePacket.class, + CustomMapPacket.class, + MapAckPacket.class, + EntitySpawnPacket.class, + NetErrorPacket.class, + PlayerAdminPacket.class, + AdministerRequestPacket.class, + TracePacket.class, }; private static ObjectIntMap> ids = new ObjectIntMap<>(); diff --git a/core/src/io/anuke/mindustry/resource/Weapon.java b/core/src/io/anuke/mindustry/resource/Weapon.java index c740518386..1359cd6ede 100644 --- a/core/src/io/anuke/mindustry/resource/Weapon.java +++ b/core/src/io/anuke/mindustry/resource/Weapon.java @@ -121,7 +121,7 @@ public class Weapon extends Upgrade{ shootInternal(p, x, y, angle); if(Net.active() && p == Vars.player){ - NetEvents.handleShoot(this, x, y, angle); + NetEvents.handleShoot(Vars.player, x, y, angle, id); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index 841c5cc5b8..7b2b719d39 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -58,12 +58,6 @@ public class DebugFragment implements Fragment { row(); new button("time max", () -> Timers.resetTime(1080000 - 60*10)); row(); - new button("clear", () -> { - enemyGroup.clear(); - state.enemies = 0; - netClient.clearRecieved(); - }); - row(); }}.end(); row(); @@ -126,7 +120,6 @@ public class DebugFragment implements Fragment { "chat.messages: " + ui.chatfrag.getMessagesSize() + "\n" + "client.connecting: " + netClient.isConnecting() + "\n" : "", "players: " + playerGroup.size(), - "enemies: " + enemyGroup.size(), "tiles: " + tileGroup.size(), "time: " + Timers.time(), world.getCore() != null && world.getCore().entity != null ? "core.health: " + world.getCore().entity.health : "", diff --git a/core/src/io/anuke/mindustry/world/Placement.java b/core/src/io/anuke/mindustry/world/Placement.java index 7bc7563190..0d650a23f8 100644 --- a/core/src/io/anuke/mindustry/world/Placement.java +++ b/core/src/io/anuke/mindustry/world/Placement.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.resource.ItemStack; @@ -13,7 +14,6 @@ import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.ProductionBlocks; import io.anuke.ucore.core.Effects; import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.SolidEntity; import static io.anuke.mindustry.Vars.*; @@ -107,14 +107,19 @@ public class Placement { rect.setCenter(offset.x + x * tilesize, offset.y + y * tilesize); synchronized (Entities.entityLock) { - for (SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)) { - if (e == null) continue; //not sure why this happens? + rect.setSize(tilesize*2f).setCenter(x*tilesize, y*tilesize); + boolean[] result = {false}; + + Units.getNearby(rect, e -> { + if (e == null) return; //not sure why this happens? Rectangle rect = e.hitbox.getRect(e.x, e.y); if (Placement.rect.overlaps(rect)) { - return false; + result[0] = true; } - } + }); + + if(result[0]) return false; } if(type.solid || type.solidifes) { diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 78e1fa7813..f441e99caf 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.math.GridPoint2; -import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.reflect.ClassReflection; import io.anuke.mindustry.entities.TileEntity; @@ -12,7 +11,6 @@ import io.anuke.mindustry.world.blocks.types.modules.LiquidModule; import io.anuke.mindustry.world.blocks.types.modules.PowerModule; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.util.Bits; -import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; @@ -86,20 +84,6 @@ public class Tile{ return (T)entity; } - public void damageNearby(int rad, int amount, float falloff){ - for(int dx = -rad; dx <= rad; dx ++){ - for(int dy = -rad; dy <= rad; dy ++){ - float dst = Vector2.dst(dx, dy, 0, 0); - if(dst > rad || (dx == 0 && dy == 0)) continue; - - Tile other = world.tile(x + dx, y + dy); - if(other != null && other.entity != null){ - other.entity.damage((int)(amount * Mathf.lerp(1f-dst/rad, 1f, falloff))); - } - } - } - } - public int id(){ return x + y * world.width(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java index 0c5a59b95b..f551a46b70 100644 --- a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java +++ b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java @@ -117,7 +117,7 @@ public class WeaponBlocks{ float len = 4f; - new TeslaOrb(tile.drawx() + Angles.trnsx(entity.rotation, len), tile.drawy() + Angles.trnsy(entity.rotation, len), range, 9).add(); + new TeslaOrb(tile.getTeam(), tile.drawx() + Angles.trnsx(entity.rotation, len), tile.drawy() + Angles.trnsy(entity.rotation, len), range, 9).add(); } }, diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java index 786d227f89..e7d28fdd35 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java @@ -2,21 +2,20 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.math.Rectangle; import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.Wall; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; -import io.anuke.ucore.entities.Entities; -import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.graphics.Draw; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.tilesize; public class Door extends Wall{ protected final Rectangle rect = new Rectangle(); @@ -68,24 +67,17 @@ public class Door extends Wall{ Block type = tile.block(); rect.setSize(type.size * tilesize, type.size * tilesize); rect.setCenter(tile.drawx(), tile.drawy()); - - for(SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ - Rectangle rect = e.hitbox.getRect(e.x, e.y); - if(this.rect.overlaps(rect)){ - return true; + boolean[] value = new boolean[1]; + + Units.getNearby(rect, unit -> { + if(value[0]) return; + if(unit.hitbox.getRect(unit.x, unit.y).overlaps(rect)){ + value[0] = true; } - } - - for(SolidEntity e : Entities.getNearby(playerGroup, x * tilesize, y * tilesize, tilesize * 2f)){ - Rectangle rect = e.hitbox.getRect(e.x, e.y); - - if(this.rect.overlaps(rect)){ - return true; - } - } + }); - return false; + return value[0]; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java index 7ee8461210..ecc81a3142 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java @@ -2,15 +2,14 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.MathUtils; - -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; @@ -32,7 +31,7 @@ public class LaserTurret extends PowerTurret{ @Override public void shoot(Tile tile){ TurretEntity entity = tile.entity(); - BaseUnit enemy = entity.target; + Unit enemy = entity.target; if(Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) < cone){ enemy.damage(damage); @@ -43,7 +42,7 @@ public class LaserTurret extends PowerTurret{ @Override public void drawLayer2(Tile tile){ TurretEntity entity = tile.entity(); - BaseUnit enemy = entity.target; + Unit enemy = entity.target; if(enemy != null && Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) <= cone){ diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java index e76394f48f..f93ae82273 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java @@ -1,17 +1,13 @@ package io.anuke.mindustry.world.blocks.types.defense; import com.badlogic.gdx.graphics.Color; -import io.anuke.mindustry.entities.Bullet; -import io.anuke.mindustry.entities.BulletType; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.*; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.world.*; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Timers; -import io.anuke.ucore.entities.Entities; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Angles; @@ -131,8 +127,8 @@ public class Turret extends Block{ if(hasAmmo(tile) || (debug && infiniteAmmo)){ if(entity.timer.get(timerTarget, targetInterval)){ - entity.target = (BaseUnit)Entities.getClosest(enemyGroup, - tile.worldx(), tile.worldy(), range, e-> e instanceof BaseUnit && !((BaseUnit)e).isDead()); + entity.target = Units.getClosestEnemies(tile.getTeam(), + tile.worldx(), tile.worldy(), range, e -> !e.isDead()); } if(entity.target != null){ @@ -240,7 +236,7 @@ public class Turret extends Block{ public TileEntity blockTarget; public int ammo; public float rotation = 90; - public BaseUnit target; + public Unit target; @Override public void write(DataOutputStream stream) throws IOException{ diff --git a/core/src/io/anuke/mindustry/world/blocks/types/generation/Generator.java b/core/src/io/anuke/mindustry/world/blocks/types/generation/Generator.java index dba4df2876..e6f8a22442 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/generation/Generator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/generation/Generator.java @@ -124,9 +124,7 @@ public class Generator extends PowerBlock{ Effects.effect(Fx.generatorexplosion, x, y); Effects.effect(Fx.shockwave, x, y); - Timers.run(12f + Mathf.random(20f), () -> { - tile.damageNearby(4, 60, 0f); - }); + //TODO better explosion effect! Effects.sound(explosionSound, x, y); }); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/generation/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/types/generation/NuclearReactor.java index 5bed41b3fe..f295a31e04 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/generation/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/generation/NuclearReactor.java @@ -130,16 +130,6 @@ public class NuclearReactor extends LiquidPowerGenerator{ if(fuel < 5 && entity.heat < 0.5f) return; - int waves = 6; - float delay = 8f; - - for(int i = 0; i < waves; i ++){ - float rad = (float)i /waves * explosionRadius; - Timers.run(i * delay, ()->{ - tile.damageNearby((int)rad, explosionDamage / waves, 0.4f); - }); - } - Effects.shake(6f, 16f, tile.worldx(), tile.worldy()); Effects.effect(explosionEffect, tile.worldx(), tile.worldy()); for(int i = 0; i < 6; i ++){ @@ -148,7 +138,7 @@ public class NuclearReactor extends LiquidPowerGenerator{ }); } - DamageArea.damageEntities(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4); + DamageArea.damage(tile.worldx(), tile.worldy(), explosionRadius * tilesize, explosionDamage * 4); for(int i = 0; i < 20; i ++){