Implemented leaky liquid explosions / New entity save system

This commit is contained in:
Anuken
2018-04-16 22:46:16 -04:00
parent a4962c5225
commit 0bebe5008b
7 changed files with 141 additions and 102 deletions

View File

@@ -1,7 +1,7 @@
#Autogenerated file. Do not modify. #Autogenerated file. Do not modify.
#Mon Apr 16 17:40:39 EDT 2018 #Mon Apr 16 22:45:45 EDT 2018
version=release version=release
androidBuildCode=930 androidBuildCode=932
name=Mindustry name=Mindustry
code=3.5 code=3.5
build=custom build build=custom build

View File

@@ -23,8 +23,14 @@ import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.*; import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timer;
import io.anuke.ucore.util.Translator;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -306,6 +312,26 @@ public class Player extends Unit{
return "Player{" + id + ", mech=" + mech.name + ", local=" + isLocal + ", " + x + ", " + y + "}\n"; return "Player{" + id + ", mech=" + mech.name + ", local=" + isLocal + ", " + x + ", " + y + "}\n";
} }
@Override
public void writeSave(DataOutputStream stream) throws IOException {
stream.writeBoolean(isLocal);
if(isLocal) super.writeSave(stream);
}
@Override
public void readSave(DataInputStream stream) throws IOException {
boolean local = stream.readBoolean();
if(local){
player.readSaveSuper(stream);
}
}
private void readSaveSuper(DataInputStream stream) throws IOException {
super.readSave(stream);
add();
}
@Override @Override
public void writeSpawn(ByteBuffer buffer) { public void writeSpawn(ByteBuffer buffer) {
buffer.put((byte)name.getBytes().length); buffer.put((byte)name.getBytes().length);

View File

@@ -0,0 +1,11 @@
package io.anuke.mindustry.entities;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**Marks an entity as serializable.*/
public interface SerializableEntity {
void writeSave(DataOutputStream stream) throws IOException;
void readSave(DataInputStream stream) throws IOException;
}

View File

@@ -10,10 +10,14 @@ import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.state;
import static io.anuke.mindustry.Vars.world; import static io.anuke.mindustry.Vars.world;
public abstract class Unit extends SyncEntity { public abstract class Unit extends SyncEntity implements SerializableEntity {
//total duration of hit effect //total duration of hit effect
public static final float hitDuration = 9f; public static final float hitDuration = 9f;
@@ -42,6 +46,32 @@ public abstract class Unit extends SyncEntity {
status.clear(); status.clear();
} }
@Override
public void writeSave(DataOutputStream stream) throws IOException {
stream.writeByte(team.ordinal());
stream.writeFloat(x);
stream.writeFloat(y);
stream.writeShort((short)health);
stream.writeByte(status.current().id);
stream.writeFloat(status.getTime());
}
@Override
public void readSave(DataInputStream stream) throws IOException {
byte team = stream.readByte();
float x = stream.readFloat();
float y = stream.readFloat();
int health = stream.readShort();
byte effect = stream.readByte();
float etime = stream.readFloat();
this.team = Team.values()[team];
this.health = health;
this.x = x;
this.y = y;
this.status.set(StatusEffect.getByID(effect), etime);
}
public Floor getFloorOn(){ public Floor getFloorOn(){
Tile tile = world.tileWorld(x, y); Tile tile = world.tileWorld(x, y);
return (Floor)(tile == null || (!(tile.floor() instanceof Floor)) ? Blocks.defaultFloor : tile.floor()); return (Floor)(tile == null || (!(tile.floor() instanceof Floor)) ? Blocks.defaultFloor : tile.floor());

View File

@@ -1,18 +1,19 @@
package io.anuke.mindustry.entities.units; package io.anuke.mindustry.entities.units;
import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timer; import io.anuke.ucore.util.Timer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import static io.anuke.mindustry.Vars.unitGroups; import static io.anuke.mindustry.Vars.unitGroups;
public class BaseUnit extends Unit { public class BaseUnit extends Unit{
public UnitType type; public UnitType type;
public Timer timer = new Timer(5); public Timer timer = new Timer(5);
public float walkTime = 0f; public float walkTime = 0f;
@@ -109,6 +110,21 @@ public class BaseUnit extends Unit {
return add(unitGroups[team.ordinal()]); return add(unitGroups[team.ordinal()]);
} }
@Override
public void writeSave(DataOutputStream stream) throws IOException {
super.writeSave(stream);
stream.writeByte(type.id);
}
@Override
public void readSave(DataInputStream stream) throws IOException {
super.readSave(stream);
byte type = stream.readByte();
this.type = UnitType.getByID(type);
add(unitGroups[team.ordinal()]);
}
@Override @Override
public void writeSpawn(ByteBuffer buffer) { public void writeSpawn(ByteBuffer buffer) {
buffer.put(type.id); buffer.put(type.id);

View File

@@ -2,22 +2,20 @@ package io.anuke.mindustry.io.versions;
import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.content.Weapons; import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.content.blocks.StorageBlocks; import io.anuke.mindustry.content.blocks.StorageBlocks;
import io.anuke.mindustry.entities.StatusEffect; import io.anuke.mindustry.entities.SerializableEntity;
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.Difficulty;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.io.SaveFileVersion;
import io.anuke.mindustry.resource.Upgrade;
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.BlockPart; import io.anuke.mindustry.world.blocks.types.BlockPart;
import io.anuke.ucore.core.Core;
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.util.Bits; import io.anuke.ucore.util.Bits;
@@ -48,6 +46,10 @@ public class Save16 extends SaveFileVersion {
float wavetime = stream.readFloat(); float wavetime = stream.readFloat();
state.difficulty = Difficulty.values()[difficulty]; state.difficulty = Difficulty.values()[difficulty];
state.mode = GameMode.values()[mode];
state.enemies = 0; //TODO display enemies correctly!
state.wave = wave;
state.wavetime = wavetime;
//block header //block header
@@ -62,71 +64,26 @@ public class Save16 extends SaveFileVersion {
map.put(id, Block.getByName(name)); map.put(id, Block.getByName(name));
} }
float playerx = stream.readFloat(); //entities
float playery = stream.readFloat();
short playerhealth = stream.readShort(); try {
byte peffect = stream.readByte();
float petime = stream.readFloat();
if(!headless) { byte groups = stream.readByte();
player.x = playerx;
player.y = playery;
player.status.set(StatusEffect.getByID(peffect), petime);
player.health = playerhealth;
state.mode = GameMode.values()[mode];
Core.camera.position.set(playerx, playery, 0);
//weapons for (int i = 0; i < groups; i++) {
control.upgrades().getWeapons().clear(); int amount = stream.readInt();
control.upgrades().getWeapons().add(Weapons.blaster); byte gid = stream.readByte();
player.weaponLeft = player.weaponRight = Weapons.blaster; EntityGroup<?> group = Entities.getGroup(gid);
for (int j = 0; j < amount; j++) {
int weapons = stream.readByte(); Entity entity = ClassReflection.newInstance(group.getType());
((SerializableEntity)entity).readSave(stream);
for (int i = 0; i < weapons; i++) { }
control.upgrades().addWeapon(Upgrade.getByID(stream.readByte()));
} }
}else{ }catch (ReflectionException e){
byte b = stream.readByte(); throw new RuntimeException(e);
for(int i = 0; i < b; i ++) stream.readByte();
} }
//enemies
byte teams = stream.readByte();
for(int i = 0; i < teams; i ++){
Team team = Team.values()[i];
EntityGroup<BaseUnit> 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();
byte effect = stream.readByte();
float etime = stream.readFloat();
BaseUnit enemy = new BaseUnit(UnitType.getByID(type), team);
enemy.health = health;
enemy.x = x;
enemy.y = y;
enemy.status.set(StatusEffect.getByID(effect), etime);
enemy.add(group);
}
}
state.enemies = 0; //TODO display enemies correctly!
state.wave = wave;
state.wavetime = wavetime;
if(!android && !headless)
player.add();
//map //map
short width = stream.readShort(); short width = stream.readShort();
@@ -204,42 +161,26 @@ public class Save16 extends SaveFileVersion {
stream.writeShort(block.id); stream.writeShort(block.id);
} }
if(!headless) { //--ENTITIES--
stream.writeFloat(player.x); //player x/y //TODO synchronized block here
stream.writeFloat(player.y);
stream.writeShort((short)player.health); //player health int groups = 0;
stream.writeByte(player.status.current().id); //status effect info for(EntityGroup<?> group : Entities.getAllGroups()){
stream.writeFloat(player.status.getTime()); if(!group.isEmpty() && group.all().get(0) instanceof SerializableEntity){
groups ++;
stream.writeByte(control.upgrades().getWeapons().size - 1); //amount of weapons
//start at 1, because the first weapon is always the starter - ignore that
for (int i = 1; i < control.upgrades().getWeapons().size; i++) {
stream.writeByte(control.upgrades().getWeapons().get(i).id); //weapon ordinal
} }
}else{
stream.writeFloat(world.getSpawnX());
stream.writeFloat(world.getSpawnY());
stream.writeInt(150);
stream.writeByte(0);
} }
//--ENEMIES-- stream.writeByte(groups);
stream.writeByte(Team.values().length); //amount of total teams (backwards compatibility)
for(Team team : Team.values()){ for(EntityGroup<?> group : Entities.getAllGroups()){
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()]; if(!group.isEmpty() && group.all().get(0) instanceof SerializableEntity){
stream.writeInt(group.size()); //amount of units in the team group stream.writeInt(group.size());
stream.writeByte(group.getID());
for(BaseUnit unit : group.all()){ for(Entity entity : group.all()){
stream.writeByte(unit.type.id); //type ((SerializableEntity)entity).writeSave(stream);
stream.writeFloat(unit.x); //x }
stream.writeFloat(unit.y); //y
stream.writeShort((short)unit.health); //health
stream.writeByte(unit.status.current().id);
stream.writeFloat(unit.status.getTime());
} }
} }

View File

@@ -10,6 +10,7 @@ import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.entities.effect.DamageArea; import io.anuke.mindustry.entities.effect.DamageArea;
import io.anuke.mindustry.entities.effect.Puddle;
import io.anuke.mindustry.graphics.DrawLayer; import io.anuke.mindustry.graphics.DrawLayer;
import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Layer;
import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Palette;
@@ -18,6 +19,7 @@ import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.resource.Liquid; import io.anuke.mindustry.resource.Liquid;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.graphics.Hue;
import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Lines;
@@ -27,6 +29,7 @@ import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.state;
import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.tilesize;
import static io.anuke.mindustry.Vars.world;
public class Block extends BaseBlock { public class Block extends BaseBlock {
private static int lastid; private static int lastid;
@@ -240,6 +243,18 @@ public class Block extends BaseBlock {
tempColor.mul(1f/units); tempColor.mul(1f/units);
Liquid liquid = tile.entity.liquid.liquid;
float splash = Mathf.clamp(tile.entity.liquid.amount/4f, 0f, 10f);
for(int i = 0; i < Mathf.clamp(tile.entity.liquid.amount / 5, 0, 30); i ++){
Timers.run(i/2, () -> {
Tile other = world.tile(tile.x + Mathf.range(size/2), tile.y + Mathf.range(size/2));
if(other != null){
Puddle.deposit(other, liquid, splash);
}
});
}
DamageArea.dynamicExplosion(x, y, flammability, explosiveness, power, tilesize * size/2f, tempColor); DamageArea.dynamicExplosion(x, y, flammability, explosiveness, power, tilesize * size/2f, tempColor);
} }