Fixed compile errors, unitification

This commit is contained in:
Anuken 2018-03-15 21:42:23 -04:00
parent 807c4688c2
commit 52c0a8e573
35 changed files with 392 additions and 347 deletions

View File

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

View File

@ -35,9 +35,6 @@ void main() {
if(any){ if(any){
gl_FragColor = u_color; gl_FragColor = u_color;
}else{ }else{
if((c.r < 0.01 && c.g < 0.01 && c.b < 0.01)){ gl_FragColor = c * v_color;
c = vec4(0.0);
}
gl_FragColor = mix(c, vec4(1.0, 1.0, 1.0, c.a), c.a) * v_color;
} }
} }

View File

@ -1,7 +1,7 @@
#Autogenerated file. Do not modify. #Autogenerated file. Do not modify.
#Thu Mar 15 12:56:43 EDT 2018 #Thu Mar 15 21:41:26 EDT 2018
version=release version=release
androidBuildCode=523 androidBuildCode=524
name=Mindustry name=Mindustry
code=3.4 code=3.4
build=custom build build=custom build

View File

@ -158,6 +158,7 @@ public class Control extends Module{
Events.on(ResetEvent.class, () -> { Events.on(ResetEvent.class, () -> {
upgrades.reset(); upgrades.reset();
player.weaponLeft = player.weaponRight = Weapon.blaster; player.weaponLeft = player.weaponRight = Weapon.blaster;
player.team = state.team;
player.add(); player.add();
player.heal(); player.heal();

View File

@ -1,9 +1,11 @@
package io.anuke.mindustry.core; package io.anuke.mindustry.core;
import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.EventType.StateChangeEvent;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Inventory; import io.anuke.mindustry.game.Inventory;
import io.anuke.mindustry.game.Team;
import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Events;
public class GameState{ public class GameState{
@ -20,6 +22,9 @@ public class GameState{
public GameMode mode = GameMode.waves; public GameMode mode = GameMode.waves;
public Difficulty difficulty = Difficulty.normal; public Difficulty difficulty = Difficulty.normal;
public boolean friendlyFire; public boolean friendlyFire;
public Team team = Team.none; //the team that the player is on
public ObjectSet<Team> enemyTeams = new ObjectSet<>(), //enemies to the player team
allyTeams = new ObjectSet<>(); //allies to the player team
public void set(State astate){ public void set(State astate){
Events.fire(StateChangeEvent.class, state, astate); Events.fire(StateChangeEvent.class, state, astate);

View File

@ -7,6 +7,7 @@ import io.anuke.mindustry.game.EventType.GameOverEvent;
import io.anuke.mindustry.game.EventType.PlayEvent; import io.anuke.mindustry.game.EventType.PlayEvent;
import io.anuke.mindustry.game.EventType.ResetEvent; import io.anuke.mindustry.game.EventType.ResetEvent;
import io.anuke.mindustry.game.EventType.WaveEvent; import io.anuke.mindustry.game.EventType.WaveEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.WaveCreator; import io.anuke.mindustry.game.WaveCreator;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.net.NetEvents;
@ -53,6 +54,10 @@ public class Logic extends Module {
state.lastUpdated = -1; state.lastUpdated = -1;
state.gameOver = false; state.gameOver = false;
state.inventory.clearItems(); state.inventory.clearItems();
state.allyTeams.clear();
state.enemyTeams.clear();
state.enemyTeams.add(Team.red);
state.team = Team.none;
Timers.clear(); Timers.clear();
Entities.clear(); Entities.clear();

View File

@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.IntSet; import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Bullet;
import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity; 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.core.Timers;
import io.anuke.ucore.entities.BaseBulletType; import io.anuke.ucore.entities.BaseBulletType;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Log;
@ -33,15 +31,20 @@ import java.nio.ByteBuffer;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class NetClient extends Module { 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 final static float playerSyncTime = 2;
private Timer timer = new Timer(5); private Timer timer = new Timer(5);
/**Whether the client is currently conencting.*/
private boolean connecting = false; 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 IntSet recieved = new IntSet();
private IntMap<Entity> recent = new IntMap<>(); /**List of recently recieved entities that have not been added to the queue yet.*/
private float timeoutTime = 0f; //data timeout counter private IntMap<SyncEntity> recent = new IntMap<>();
/**Counter for data timeout.*/
private float timeoutTime = 0f;
public NetClient(){ public NetClient(){
@ -53,7 +56,7 @@ public class NetClient extends Module {
recent.clear(); recent.clear();
timeoutTime = 0f; timeoutTime = 0f;
connecting = true; connecting = true;
kicked = false; quiet = false;
ui.chatfrag.clearMessages(); ui.chatfrag.clearMessages();
ui.loadfrag.hide(); ui.loadfrag.hide();
@ -78,7 +81,7 @@ public class NetClient extends Module {
}); });
Net.handleClient(Disconnect.class, packet -> { Net.handleClient(Disconnect.class, packet -> {
if (kicked) return; if (quiet) return;
Timers.runTask(3f, ui.loadfrag::hide); Timers.runTask(3f, ui.loadfrag::hide);
@ -187,23 +190,29 @@ public class NetClient extends Module {
Log.info("Recieved entity {0}", packet.entity.id); Log.info("Recieved entity {0}", packet.entity.id);
}); });
Net.handleClient(EnemyDeathPacket.class, packet -> { Net.handleClient(EntityDeathPacket.class, packet -> {
BaseUnit enemy = enemyGroup.getByID(packet.id); EntityGroup group = Entities.getGroup(packet.group);
if (enemy != null){ SyncEntity entity = (SyncEntity) group.getByID(packet.id);
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);
}
recieved.add(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 -> { Net.handleClient(EntityShootPacket.class, packet -> {
//TODO shoot effects for enemies, clientside as well as serverside BulletType type = BaseBulletType.getByID(packet.bulletid);
BulletType type = (BulletType) BaseBulletType.getByID(packet.type); EntityGroup group = Entities.getGroup(packet.groupid);
Entity owner = enemyGroup.getByID(packet.owner); SyncEntity owner = (SyncEntity) group.getByID(packet.entityid);
new Bullet(type, owner, packet.x, packet.y, packet.angle).add();
owner.onRemoteShoot(type, packet.x, packet.y, packet.rotation, packet.data);
}); });
Net.handleClient(BlockDestroyPacket.class, packet -> { Net.handleClient(BlockDestroyPacket.class, packet -> {
@ -231,7 +240,7 @@ public class NetClient extends Module {
}); });
Net.handleClient(KickPacket.class, packet -> { Net.handleClient(KickPacket.class, packet -> {
kicked = true; quiet = true;
Net.disconnect(); Net.disconnect();
state.set(State.menu); state.set(State.menu);
if(!packet.reason.quiet) ui.showError("$text.server.kicked." + packet.reason.name()); 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 != null){
world.getCore().entity.onDeath(true); world.getCore().entity.onDeath(true);
} }
kicked = true; quiet = true;
ui.restart.show(); ui.restart.show();
}); });
@ -279,7 +288,7 @@ public class NetClient extends Module {
if(timeoutTime > dataTimeout){ if(timeoutTime > dataTimeout){
Log.err("Failed to load data!"); Log.err("Failed to load data!");
ui.loadfrag.hide(); ui.loadfrag.hide();
kicked = true; quiet = true;
ui.showError("$text.disconnect.data"); ui.showError("$text.disconnect.data");
Net.disconnect(); Net.disconnect();
timeoutTime = 0f; timeoutTime = 0f;
@ -306,7 +315,7 @@ public class NetClient extends Module {
} }
public void disconnectQuietly(){ public void disconnectQuietly(){
kicked = true; quiet = true;
Net.disconnect(); Net.disconnect();
} }

View File

@ -3,9 +3,11 @@ package io.anuke.mindustry.core;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.SendMode; 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.Upgrade;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
@ -15,13 +17,6 @@ public class NetCommon extends Module {
public NetCommon(){ 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) -> { Net.handle(ChatPacket.class, (packet) -> {
ui.chatfrag.addMessage(packet.text, colorizeName(packet.id, packet.name)); ui.chatfrag.addMessage(packet.text, colorizeName(packet.id, packet.name));
}); });
@ -31,8 +26,8 @@ public class NetCommon extends Module {
if (player == null) return; if (player == null) return;
player.weaponLeft = (Weapon) Upgrade.getByID(packet.left); player.weaponLeft = Upgrade.getByID(packet.left);
player.weaponRight = (Weapon) Upgrade.getByID(packet.right); player.weaponRight = Upgrade.getByID(packet.right);
}); });
Net.handle(BlockTapPacket.class, (packet) -> { Net.handle(BlockTapPacket.class, (packet) -> {
@ -44,13 +39,6 @@ public class NetCommon extends Module {
Tile tile = world.tile(packet.position); Tile tile = world.tile(packet.position);
if (tile != null) tile.block().configure(tile, packet.data); 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){ public void sendMessage(String message){

View File

@ -2,6 +2,7 @@ package io.anuke.mindustry.core;
import com.badlogic.gdx.utils.*; import com.badlogic.gdx.utils.*;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.game.EventType.GameOverEvent; 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.mindustry.world.Placement;
import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Events;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.BaseBulletType;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.modules.Module; 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 //...don't do anything here as it's already handled by the packet itself
}); });
Net.handleServer(ShootPacket.class, (id, packet) -> { Net.handleServer(EntityShootPacket.class, (id, packet) -> {
packet.playerid = connections.get(id).id; 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); Net.sendExcept(id, packet, SendMode.udp);
}); });
@ -201,7 +210,7 @@ public class NetServer extends Module{
}); });
Net.handleServer(ChatPacket.class, (id, packet) -> { Net.handleServer(ChatPacket.class, (id, packet) -> {
if(!Timers.get("chatFlood" + id, 20)){ if(!Timers.get("chatFlood" + id, 30)){
ChatPacket warn = new ChatPacket(); ChatPacket warn = new ChatPacket();
warn.text = "[scarlet]You are sending messages too quickly."; warn.text = "[scarlet]You are sending messages too quickly.";
Net.sendTo(id, warn, SendMode.tcp); 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.id = connections.get(id).id;
packet.group = (byte)connections.get(id).getGroup().getID();
Net.sendExcept(id, packet, SendMode.tcp); Net.sendExcept(id, packet, SendMode.tcp);
}); });

View File

@ -217,7 +217,9 @@ public class Renderer extends RendererModule{
Shaders.outline.color.set(team.color); Shaders.outline.color.set(team.color);
Graphics.beginShaders(Shaders.outline); Graphics.beginShaders(Shaders.outline);
//Graphics.shader(Shaders.hit);
drawTeam(team, flying); drawTeam(team, flying);
//Graphics.shader();
Graphics.endShaders(); Graphics.endShaders();
} }
} }

View File

@ -1,6 +1,7 @@
package io.anuke.mindustry.entities; package io.anuke.mindustry.entities;
import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.entities.BulletEntity; import io.anuke.ucore.entities.BulletEntity;
import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.Entity;
@ -40,6 +41,10 @@ public class Bullet extends BulletEntity{
return owner instanceof BaseUnit; return owner instanceof BaseUnit;
} }
public Team team(){
return ((Unit)owner).team;
}
@Override @Override
public void update(){ public void update(){
super.update(); super.update();

View File

@ -3,12 +3,11 @@ package io.anuke.mindustry.entities;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import io.anuke.mindustry.entities.effect.DamageArea; import io.anuke.mindustry.entities.effect.DamageArea;
import io.anuke.mindustry.entities.effect.EMP; import io.anuke.mindustry.entities.effect.EMP;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Fx;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.BaseBulletType; import io.anuke.ucore.entities.BaseBulletType;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
@ -122,7 +121,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b); Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shellexplosion, 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) { flak = new BulletType(2.9f, 8) {
@ -202,7 +201,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b); Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shockwaveSmall, 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){ yellowshell = new BulletType(1.2f, 20){
@ -233,7 +232,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b); Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shockwaveSmall, 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){ blast = new BulletType(1.1f, 90){
@ -371,7 +370,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.clusterbomb, b); 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) { vulcan = new BulletType(4.5f, 12) {
@ -450,7 +449,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
} }
public void init(Bullet b) { 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) { public void draw(Bullet b) {

View File

@ -57,6 +57,13 @@ public class Player extends Unit{
heal(); 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 @Override
public float getMass(){ public float getMass(){
return mech.mass; return mech.mass;
@ -105,8 +112,8 @@ public class Player extends Unit{
ui.hudfrag.fadeRespawn(true); ui.hudfrag.fadeRespawn(true);
} }
/**called when a remote player death event is recieved*/ @Override
public void doRespawn(){ public void onRemoteDeath(){
dead = true; dead = true;
Effects.effect(Fx.explosion, this); Effects.effect(Fx.explosion, this);
Effects.shake(4f, 5f, this); Effects.shake(4f, 5f, this);
@ -136,7 +143,7 @@ public class Player extends Unit{
float ft = Mathf.sin(walktime, 6f, 2f); float ft = Mathf.sin(walktime, 6f, 2f);
Draw.alpha(hitTime / hitDuration); //Draw.alpha(hitTime / hitDuration);
for(int i : Mathf.signs){ for(int i : Mathf.signs){
tr.trns(footRotation, ft * i); 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.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, rotation - 90);
} }
Draw.alpha(1f); //Draw.alpha(1f);
x = px; x = px;
y = py; y = py;

View File

@ -14,15 +14,24 @@ import static io.anuke.mindustry.Vars.threads;
/**Base class for any entity that needs to be synced across clients.*/ /**Base class for any entity that needs to be synced across clients.*/
public abstract class SyncEntity extends DestructibleEntity{ 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*/ /**smoothed position and rotation*/
private Vector3 spos = new Vector3(); private Vector3 spos = new Vector3();
/**the general rotation.*/ /**the general rotation.*/
public float 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 writeSpawn(ByteBuffer data);
public abstract void readSpawn(ByteBuffer data); public abstract void readSpawn(ByteBuffer data);
//Read and write sync data, usually position
public abstract void write(ByteBuffer data); public abstract void write(ByteBuffer data);
public abstract void read(ByteBuffer data, long time); public abstract void read(ByteBuffer data, long time);
@ -101,6 +110,7 @@ public abstract class SyncEntity extends DestructibleEntity{
} }
public void update(){ public void update(){
//TODO prevent rubberbanding from getting too bad, clamp values?
time += 1f / spacing * Math.min(Timers.delta(), 1f); time += 1f / spacing * Math.min(Timers.delta(), 1f);

View File

@ -1,18 +1,24 @@
package io.anuke.mindustry.entities; package io.anuke.mindustry.entities;
import com.badlogic.gdx.math.Rectangle; 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.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.function.Consumer; 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.*;
import static io.anuke.mindustry.Vars.unitGroups;
/**Utility class for unit-based interactions.*/ /**Utility class for unit and team interactions.*/
public class Units { public class Units {
private static Rectangle rect = new Rectangle();
/**Iterates over all units on all teams, including players.*/
public static void allUnits(Consumer<Unit> cons){ public static void allUnits(Consumer<Unit> cons){
//check all unit groups first
for(EntityGroup<BaseUnit> group : unitGroups){ for(EntityGroup<BaseUnit> group : unitGroups){
if(!group.isEmpty()){ if(!group.isEmpty()){
for(BaseUnit unit : group.all()){ for(BaseUnit unit : group.all()){
@ -21,12 +27,73 @@ public class Units {
} }
} }
//then check all player groups
for(Player player : playerGroup.all()){ for(Player player : playerGroup.all()){
cons.accept(player); cons.accept(player);
} }
} }
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){ public static Unit getClosestEnemies(Team team, float x, float y, float range, Predicate<Unit> 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<Unit> cons){
for(Team team : Team.values()){
EntityGroup<BaseUnit> 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<Unit> cons){
//check if it's an ally team to the 'main team'
boolean ally = state.team == team || state.allyTeams.contains(team);
ObjectSet<Team> targets = ally ? state.enemyTeams : state.allyTeams;
for(Team other : targets){
EntityGroup<BaseUnit> 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;
} }
} }

View File

@ -2,27 +2,27 @@ package io.anuke.mindustry.entities.effect;
import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2; 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.mindustry.world.Tile;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect; 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.function.Consumer;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Physics; import io.anuke.ucore.util.Physics;
import io.anuke.ucore.util.Translator; 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{ public class DamageArea{
private static Rectangle rect = new Rectangle(); private static Rectangle rect = new Rectangle();
private static Translator tr = new Translator(); private static Translator tr = new Translator();
//only for entities, not tiles (yet!) /**Damages entities in a line.
public static void damageLine(Entity owner, Effect effect, float x, float y, float angle, float length, int damage){ * 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); tr.trns(angle, length);
rect.setPosition(x, y).setSize(tr.x, tr.y); rect.setPosition(x, y).setSize(tr.x, tr.y);
float x2 = tr.x + x, y2 = tr.y + y; float x2 = tr.x + x, y2 = tr.y + y;
@ -44,10 +44,8 @@ public class DamageArea{
rect.width += expand*2; rect.width += expand*2;
rect.height += expand*2; rect.height += expand*2;
Consumer<SolidEntity> cons = e -> { Consumer<Unit> cons = e -> {
if(e == owner) return; Rectangle other = e.hitbox.getRect(e.x, e.y);
DestructibleEntity enemy = (DestructibleEntity) e;
Rectangle other = enemy.hitbox.getRect(enemy.x, enemy.y);
other.y -= expand; other.y -= expand;
other.x -= expand; other.x -= expand;
other.width += expand * 2; other.width += expand * 2;
@ -57,53 +55,49 @@ public class DamageArea{
if (vec != null) { if (vec != null) {
Effects.effect(effect, vec.x, vec.y); Effects.effect(effect, vec.x, vec.y);
enemy.damage(damage); e.damage(damage);
} }
}; };
Entities.getNearby(enemyGroup, rect, cons); Units.getNearbyEnemies(team, rect, cons);
if(state.friendlyFire) Entities.getNearby(playerGroup, rect, cons);
} }
public static void damageEntities(float x, float y, float radius, int damage){ /**Damages everything in a radius.*/
damage(true, x, y, radius, damage); public static void damage(float x, float y, float radius, int damage){
damage(null, 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);
}
} }
public static void damage(boolean enemies, float x, float y, float radius, int damage){ /**Damages all entities and blocks in a radius that are enemies of the team.*/
Consumer<SolidEntity> cons = entity -> { public static void damage(Team team, float x, float y, float radius, int damage){
DestructibleEntity enemy = (DestructibleEntity)entity; Consumer<Unit> cons = entity -> {
if(enemy.distanceTo(x, y) > radius){ if(entity.distanceTo(x, y) > radius){
return; return;
} }
int amount = calculateDamage(x, y, enemy.x, enemy.y, radius, damage); int amount = calculateDamage(x, y, entity.x, entity.y, radius, damage);
enemy.damage(amount); entity.damage(amount);
}; };
if(enemies){ rect.setSize(radius *2).setCenter(x, y);
Entities.getNearby(enemyGroup, x, y, radius*2, cons); if(team != null) {
Units.getNearbyEnemies(team, rect, cons);
}else{ }else{
int trad = (int)(radius / tilesize); Units.getNearby(rect, cons);
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); int trad = (int)(radius / tilesize);
if(tile != null && tile.entity != null && Vector2.dst(dx, dy, 0, 0) <= trad){ for(int dx = -trad; dx <= trad; dx ++){
int amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage); for(int dy= -trad; dy <= trad; dy ++){
tile.entity.damage(amount); 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 dist = Vector2.dst(x, y, tx, ty);
float scaled = 1f - dist/radius; float scaled = 1f - dist/radius;
return (int)(damage * scaled); return (int)(damage * scaled);

View File

@ -1,40 +1,45 @@
package io.anuke.mindustry.entities.effect; package io.anuke.mindustry.entities.effect;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Fx;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.enemyGroup;
public class TeslaOrb extends Entity{ public class TeslaOrb extends Entity{
private Array<Vector2> points = new Array<>(); private final static Rectangle rect = new Rectangle();
private ObjectSet<BaseUnit> hit = new ObjectSet<>();
private int damage = 0;
private float range = 0;
private float lifetime = 30f;
private float life = 0f;
private Vector2 vector = new Vector2();
public TeslaOrb(float x, float y, float range, int damage){ private final Array<Vector2> points = new Array<>();
private final ObjectSet<BaseUnit> 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 float curx = x, cury = y;
private boolean done = false;
public TeslaOrb(Team team, float x, float y, float range, int damage){
set(x, y); set(x, y);
this.team = team;
this.damage = damage; this.damage = damage;
this.range = range; this.range = range;
} }
void shock(){ void shock(){
float stopchance = 0.1f; float stopchance = 0.1f;
float curx = x, cury = y;
float shake = 3f; float shake = 3f;
int max = 7; int max = 7;
@ -44,18 +49,18 @@ public class TeslaOrb extends Entity{
break; break;
} }
Array<SolidEntity> enemies = Entities.getNearby(enemyGroup, curx, cury, range*2f); rect.setSize(range*2f).setCenter(curx, cury);
for(SolidEntity entity : enemies){ Units.getNearbyEnemies(team, rect, entity -> {
if(entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((BaseUnit)entity)){ if(!done && entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((BaseUnit)entity)){
hit.add((BaseUnit)entity); hit.add((BaseUnit)entity);
points.add(new Vector2(entity.x + Mathf.range(shake), entity.y + Mathf.range(shake))); points.add(new Vector2(entity.x + Mathf.range(shake), entity.y + Mathf.range(shake)));
damageEnemy((BaseUnit)entity); damageEnemy((BaseUnit)entity);
curx = entity.x; curx = entity.x;
cury = entity.y; cury = entity.y;
break; done = true;
} }
} });
} }
if(points.size == 0){ if(points.size == 0){
@ -107,11 +112,6 @@ public class TeslaOrb extends Entity{
Draw.rect("circle", x, y, rad, rad); 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(); Draw.reset();
previous = enemy; previous = enemy;

View File

@ -1,6 +1,7 @@
package io.anuke.mindustry.entities.units; package io.anuke.mindustry.entities.units;
import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.Bullet;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Unit;
import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.entities.SolidEntity;
@ -63,9 +64,19 @@ public class BaseUnit extends Unit {
hitTime = hitDuration; 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 @Override
public void onDeath(){ public void onDeath(){
type.onDeath(this, false); type.onDeath(this);
}
@Override
public void onRemoteDeath(){
type.onRemoteDeath(this);
} }
@Override @Override

View File

@ -67,7 +67,11 @@ public class UnitType {
//TODO //TODO
} }
public void onDeath(BaseUnit enemy, boolean force){ public void onDeath(BaseUnit enemy){
//TODO
}
public void onRemoteDeath(BaseUnit enemy){
//TODO //TODO
} }

View File

@ -3,7 +3,7 @@ package io.anuke.mindustry.game;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
public enum Team { public enum Team {
none(Color.GRAY), none(Color.DARK_GRAY),
blue(Color.BLUE), blue(Color.BLUE),
red(Color.RED); red(Color.RED);

View File

@ -15,6 +15,7 @@ public class Shaders{
public static final SurfaceShader water = new SurfaceShader("water"); public static final SurfaceShader water = new SurfaceShader("water");
public static final SurfaceShader lava = new SurfaceShader("lava"); public static final SurfaceShader lava = new SurfaceShader("lava");
public static final SurfaceShader oil = new SurfaceShader("oil"); 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(); private static final Vector2 vec = new Vector2();

View File

@ -6,6 +6,7 @@ import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.entities.units.UnitType; import io.anuke.mindustry.entities.units.UnitType;
import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.io.SaveFileVersion;
import io.anuke.mindustry.io.SaveMeta; import io.anuke.mindustry.io.SaveMeta;
import io.anuke.mindustry.resource.Item; 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.BlockPart;
import io.anuke.mindustry.world.blocks.types.Rock; import io.anuke.mindustry.world.blocks.types.Rock;
import io.anuke.ucore.core.Core; 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.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@ -84,7 +85,6 @@ public class Save16 extends SaveFileVersion {
Core.camera.position.set(playerx, playery, 0); Core.camera.position.set(playerx, playery, 0);
//weapons //weapons
control.upgrades().getWeapons().clear(); control.upgrades().getWeapons().clear();
control.upgrades().getWeapons().add(Weapon.blaster); control.upgrades().getWeapons().add(Weapon.blaster);
player.weaponLeft = player.weaponRight = Weapon.blaster; player.weaponLeft = player.weaponRight = Weapon.blaster;
@ -117,26 +117,28 @@ public class Save16 extends SaveFileVersion {
//enemies //enemies
int enemies = stream.readInt(); byte teams = stream.readByte();
for(int i = 0; i < enemies; i ++){ for(int i = 0; i < teams; i ++){
byte type = stream.readByte(); EntityGroup<BaseUnit> group = unitGroups[i];
float x = stream.readFloat();
float y = stream.readFloat(); int amount = stream.readInt();
int health = stream.readShort();
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)); BaseUnit enemy = new BaseUnit(UnitType.getByID(type));
enemy.health = health; enemy.health = health;
enemy.x = x; enemy.x = x;
enemy.y = y; enemy.y = y;
enemy.add(enemyGroup); enemy.add(group);
}catch (Exception e){
throw new RuntimeException(e);
} }
} }
state.enemies = enemies; state.enemies = 0; //TODO display enemies correctly!
state.wave = wave; state.wave = wave;
state.wavetime = wavetime; state.wavetime = wavetime;
@ -186,9 +188,11 @@ public class Save16 extends SaveFileVersion {
} }
if(tile.entity != null){ if(tile.entity != null){
byte team = stream.readByte();
byte rotation = stream.readByte(); byte rotation = stream.readByte();
short health = stream.readShort(); short health = stream.readShort();
tile.setTeam(Team.values()[team]);
tile.entity.health = health; tile.entity.health = health;
tile.setRotation(rotation); tile.setRotation(rotation);
@ -265,17 +269,18 @@ public class Save16 extends SaveFileVersion {
} }
//--ENEMIES-- //--ENEMIES--
stream.writeByte(Team.values().length); //amount of total teams (backwards compatibility)
EntityContainer<BaseUnit> enemies = enemyGroup.all(); for(Team team : Team.values()){
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
stream.writeInt(group.size()); //amount of units in the team group
stream.writeInt(enemies.size()); //enemy amount for(BaseUnit unit : group.all()){
stream.writeByte(unit.type.id); //type
for(int i = 0; i < enemies.size(); i ++){ stream.writeFloat(unit.x); //x
BaseUnit enemy = enemies.get(i); stream.writeFloat(unit.y); //y
stream.writeByte(enemy.type.id); //type stream.writeShort(unit.health); //health
stream.writeFloat(enemy.x); //x }
stream.writeFloat(enemy.y); //y
stream.writeShort(enemy.health); //health
} }
//--MAP DATA-- //--MAP DATA--
@ -329,6 +334,7 @@ public class Save16 extends SaveFileVersion {
if(tile.block() instanceof BlockPart) stream.writeByte(tile.link); if(tile.block() instanceof BlockPart) stream.writeByte(tile.link);
if(tile.entity != null){ if(tile.entity != null){
stream.writeByte(tile.getTeam().ordinal());
stream.writeByte(tile.getRotation()); //rotation stream.writeByte(tile.getRotation()); //rotation
stream.writeShort((short)tile.entity.health); //health stream.writeShort((short)tile.entity.health); //health

View File

@ -1,16 +1,15 @@
package io.anuke.mindustry.net; package io.anuke.mindustry.net;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.entities.TileEntity; 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.Net.SendMode;
import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.entities.Entity;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@ -29,20 +28,11 @@ public class NetEvents {
Net.send(new GameOverPacket(), SendMode.tcp); 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){ public static void handleUnitDeath(Unit enemy){
EnemyDeathPacket packet = new EnemyDeathPacket(); EntityDeathPacket packet = new EntityDeathPacket();
packet.id = enemy.id; packet.id = enemy.id;
packet.group = (byte)enemy.getGroup().getID();
Net.send(packet, SendMode.tcp); Net.send(packet, SendMode.tcp);
} }
@ -60,7 +50,7 @@ public class NetEvents {
} }
public static void handlePlayerDeath(){ public static void handlePlayerDeath(){
PlayerDeathPacket packet = new PlayerDeathPacket(); EntityDeathPacket packet = new EntityDeathPacket();
packet.id = Vars.player.id; packet.id = Vars.player.id;
Net.send(packet, SendMode.tcp); Net.send(packet, SendMode.tcp);
} }
@ -100,13 +90,14 @@ public class NetEvents {
Net.send(packet, SendMode.tcp); Net.send(packet, SendMode.tcp);
} }
public static void handleShoot(Weapon weapon, float x, float y, float angle){ public static void handleShoot(SyncEntity entity, float x, float y, float angle, short data){
ShootPacket packet = new ShootPacket(); EntityShootPacket packet = new EntityShootPacket();
packet.weaponid = weapon.id; packet.groupid = (byte)entity.getGroup().getID();
packet.x = x; packet.x = x;
packet.y = y; packet.y = y;
packet.data = data;
packet.rotation = angle; packet.rotation = angle;
packet.playerid = Vars.player.id; packet.entityid = entity.id;
Net.send(packet, SendMode.udp); Net.send(packet, SendMode.udp);
} }

View File

@ -161,60 +161,31 @@ public class Packets {
} }
} }
//not a real packet. public static class EntityShootPacket implements Packet{
public static class EffectPacket{
public int id;
public float x, y, rotation; public float x, y, rotation;
public int color; public short bulletid;
} public byte groupid;
public short data;
public static class ShootPacket implements Packet{ public int entityid;
public byte weaponid;
public float x, y, rotation;
public int playerid;
@Override @Override
public void write(ByteBuffer buffer) { public void write(ByteBuffer buffer) {
buffer.put(weaponid); buffer.put(groupid);
buffer.putInt(entityid);
buffer.putFloat(x); buffer.putFloat(x);
buffer.putFloat(y); buffer.putFloat(y);
buffer.putFloat(rotation); buffer.putFloat(rotation);
buffer.putInt(playerid); buffer.putShort(bulletid);
} }
@Override @Override
public void read(ByteBuffer buffer) { public void read(ByteBuffer buffer) {
weaponid = buffer.get(); groupid = buffer.get();
entityid = buffer.getInt();
x = buffer.getFloat(); x = buffer.getFloat();
y = buffer.getFloat(); y = buffer.getFloat();
rotation = buffer.getFloat(); rotation = buffer.getFloat();
playerid = buffer.getInt(); bulletid = buffer.getShort();
}
}
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();
} }
} }
@ -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; public int id;
@Override @Override
public void write(ByteBuffer buffer) { public void write(ByteBuffer buffer) {
buffer.put(group);
buffer.putInt(id); buffer.putInt(id);
} }
@Override @Override
public void read(ByteBuffer buffer) { public void read(ByteBuffer buffer) {
group = buffer.get();
id = buffer.getInt(); 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{ public static class CustomMapPacket extends Streamable{
} }

View File

@ -8,40 +8,38 @@ import io.anuke.mindustry.net.Streamable.StreamChunk;
public class Registrator { public class Registrator {
private static Class<?>[] classes = { private static Class<?>[] classes = {
StreamBegin.class, StreamBegin.class,
StreamChunk.class, StreamChunk.class,
WorldData.class, WorldData.class,
SyncPacket.class, SyncPacket.class,
PositionPacket.class, PositionPacket.class,
ShootPacket.class, EntityShootPacket.class,
PlacePacket.class, PlacePacket.class,
BreakPacket.class, BreakPacket.class,
StateSyncPacket.class, StateSyncPacket.class,
BlockSyncPacket.class, BlockSyncPacket.class,
BulletPacket.class, EntityDeathPacket.class,
EnemyDeathPacket.class, BlockUpdatePacket.class,
BlockUpdatePacket.class, BlockDestroyPacket.class,
BlockDestroyPacket.class, ConnectPacket.class,
ConnectPacket.class, DisconnectPacket.class,
DisconnectPacket.class, ChatPacket.class,
ChatPacket.class, KickPacket.class,
KickPacket.class, UpgradePacket.class,
UpgradePacket.class, WeaponSwitchPacket.class,
WeaponSwitchPacket.class, BlockTapPacket.class,
BlockTapPacket.class, BlockConfigPacket.class,
BlockConfigPacket.class, EntityRequestPacket.class,
EntityRequestPacket.class, ConnectConfirmPacket.class,
ConnectConfirmPacket.class, GameOverPacket.class,
GameOverPacket.class, FriendlyFireChangePacket.class,
FriendlyFireChangePacket.class, CustomMapPacket.class,
PlayerDeathPacket.class, MapAckPacket.class,
CustomMapPacket.class, EntitySpawnPacket.class,
MapAckPacket.class, NetErrorPacket.class,
EntitySpawnPacket.class, PlayerAdminPacket.class,
NetErrorPacket.class, AdministerRequestPacket.class,
PlayerAdminPacket.class, TracePacket.class,
AdministerRequestPacket.class,
TracePacket.class,
}; };
private static ObjectIntMap<Class<?>> ids = new ObjectIntMap<>(); private static ObjectIntMap<Class<?>> ids = new ObjectIntMap<>();

View File

@ -121,7 +121,7 @@ public class Weapon extends Upgrade{
shootInternal(p, x, y, angle); shootInternal(p, x, y, angle);
if(Net.active() && p == Vars.player){ if(Net.active() && p == Vars.player){
NetEvents.handleShoot(this, x, y, angle); NetEvents.handleShoot(Vars.player, x, y, angle, id);
} }
} }

View File

@ -58,12 +58,6 @@ public class DebugFragment implements Fragment {
row(); row();
new button("time max", () -> Timers.resetTime(1080000 - 60*10)); new button("time max", () -> Timers.resetTime(1080000 - 60*10));
row(); row();
new button("clear", () -> {
enemyGroup.clear();
state.enemies = 0;
netClient.clearRecieved();
});
row();
}}.end(); }}.end();
row(); row();
@ -126,7 +120,6 @@ public class DebugFragment implements Fragment {
"chat.messages: " + ui.chatfrag.getMessagesSize() + "\n" + "chat.messages: " + ui.chatfrag.getMessagesSize() + "\n" +
"client.connecting: " + netClient.isConnecting() + "\n" : "", "client.connecting: " + netClient.isConnecting() + "\n" : "",
"players: " + playerGroup.size(), "players: " + playerGroup.size(),
"enemies: " + enemyGroup.size(),
"tiles: " + tileGroup.size(), "tiles: " + tileGroup.size(),
"time: " + Timers.time(), "time: " + Timers.time(),
world.getCore() != null && world.getCore().entity != null ? "core.health: " + world.getCore().entity.health : "", world.getCore() != null && world.getCore().entity != null ? "core.health: " + world.getCore().entity.health : "",

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.resource.ItemStack; 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.mindustry.world.blocks.ProductionBlocks;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.SolidEntity;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@ -107,14 +107,19 @@ public class Placement {
rect.setCenter(offset.x + x * tilesize, offset.y + y * tilesize); rect.setCenter(offset.x + x * tilesize, offset.y + y * tilesize);
synchronized (Entities.entityLock) { synchronized (Entities.entityLock) {
for (SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)) { rect.setSize(tilesize*2f).setCenter(x*tilesize, y*tilesize);
if (e == null) continue; //not sure why this happens? 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); Rectangle rect = e.hitbox.getRect(e.x, e.y);
if (Placement.rect.overlaps(rect)) { if (Placement.rect.overlaps(rect)) {
return false; result[0] = true;
} }
} });
if(result[0]) return false;
} }
if(type.solid || type.solidifes) { if(type.solid || type.solidifes) {

View File

@ -1,7 +1,6 @@
package io.anuke.mindustry.world; package io.anuke.mindustry.world;
import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.reflect.ClassReflection; import com.badlogic.gdx.utils.reflect.ClassReflection;
import io.anuke.mindustry.entities.TileEntity; 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.mindustry.world.blocks.types.modules.PowerModule;
import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.util.Bits; 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.tilesize;
import static io.anuke.mindustry.Vars.world; import static io.anuke.mindustry.Vars.world;
@ -86,20 +84,6 @@ public class Tile{
return (T)entity; 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(){ public int id(){
return x + y * world.width(); return x + y * world.width();
} }

View File

@ -117,7 +117,7 @@ public class WeaponBlocks{
float len = 4f; 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();
} }
}, },

View File

@ -2,21 +2,20 @@ package io.anuke.mindustry.world.blocks.types.defense;
import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Rectangle;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.types.Wall; import io.anuke.mindustry.world.blocks.types.Wall;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect; 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 io.anuke.ucore.graphics.Draw;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.tilesize;
public class Door extends Wall{ public class Door extends Wall{
protected final Rectangle rect = new Rectangle(); protected final Rectangle rect = new Rectangle();
@ -69,23 +68,16 @@ public class Door extends Wall{
rect.setSize(type.size * tilesize, type.size * tilesize); rect.setSize(type.size * tilesize, type.size * tilesize);
rect.setCenter(tile.drawx(), tile.drawy()); rect.setCenter(tile.drawx(), tile.drawy());
for(SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ boolean[] value = new boolean[1];
Rectangle rect = e.hitbox.getRect(e.x, e.y);
if(this.rect.overlaps(rect)){ Units.getNearby(rect, unit -> {
return true; 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)){ return value[0];
Rectangle rect = e.hitbox.getRect(e.x, e.y);
if(this.rect.overlaps(rect)){
return true;
}
}
return false;
} }
@Override @Override

View File

@ -2,15 +2,14 @@ package io.anuke.mindustry.world.blocks.types.defense;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.Layer;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
@ -32,7 +31,7 @@ public class LaserTurret extends PowerTurret{
@Override @Override
public void shoot(Tile tile){ public void shoot(Tile tile){
TurretEntity entity = tile.entity(); 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){ if(Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) < cone){
enemy.damage(damage); enemy.damage(damage);
@ -43,7 +42,7 @@ public class LaserTurret extends PowerTurret{
@Override @Override
public void drawLayer2(Tile tile){ public void drawLayer2(Tile tile){
TurretEntity entity = tile.entity(); TurretEntity entity = tile.entity();
BaseUnit enemy = entity.target; Unit enemy = entity.target;
if(enemy != null && if(enemy != null &&
Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) <= cone){ Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) <= cone){

View File

@ -1,17 +1,13 @@
package io.anuke.mindustry.world.blocks.types.defense; package io.anuke.mindustry.world.blocks.types.defense;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Angles;
@ -131,8 +127,8 @@ public class Turret extends Block{
if(hasAmmo(tile) || (debug && infiniteAmmo)){ if(hasAmmo(tile) || (debug && infiniteAmmo)){
if(entity.timer.get(timerTarget, targetInterval)){ if(entity.timer.get(timerTarget, targetInterval)){
entity.target = (BaseUnit)Entities.getClosest(enemyGroup, entity.target = Units.getClosestEnemies(tile.getTeam(),
tile.worldx(), tile.worldy(), range, e-> e instanceof BaseUnit && !((BaseUnit)e).isDead()); tile.worldx(), tile.worldy(), range, e -> !e.isDead());
} }
if(entity.target != null){ if(entity.target != null){
@ -240,7 +236,7 @@ public class Turret extends Block{
public TileEntity blockTarget; public TileEntity blockTarget;
public int ammo; public int ammo;
public float rotation = 90; public float rotation = 90;
public BaseUnit target; public Unit target;
@Override @Override
public void write(DataOutputStream stream) throws IOException{ public void write(DataOutputStream stream) throws IOException{

View File

@ -124,9 +124,7 @@ public class Generator extends PowerBlock{
Effects.effect(Fx.generatorexplosion, x, y); Effects.effect(Fx.generatorexplosion, x, y);
Effects.effect(Fx.shockwave, x, y); Effects.effect(Fx.shockwave, x, y);
Timers.run(12f + Mathf.random(20f), () -> { //TODO better explosion effect!
tile.damageNearby(4, 60, 0f);
});
Effects.sound(explosionSound, x, y); Effects.sound(explosionSound, x, y);
}); });

View File

@ -130,16 +130,6 @@ public class NuclearReactor extends LiquidPowerGenerator{
if(fuel < 5 && entity.heat < 0.5f) return; 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.shake(6f, 16f, tile.worldx(), tile.worldy());
Effects.effect(explosionEffect, tile.worldx(), tile.worldy()); Effects.effect(explosionEffect, tile.worldx(), tile.worldy());
for(int i = 0; i < 6; i ++){ 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 ++){ for(int i = 0; i < 20; i ++){