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.
#Mon Apr 16 17:40:39 EDT 2018
#Mon Apr 16 22:45:45 EDT 2018
version=release
androidBuildCode=930
androidBuildCode=932
name=Mindustry
code=3.5
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.entities.SolidEntity;
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 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";
}
@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
public void writeSpawn(ByteBuffer buffer) {
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.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.world;
public abstract class Unit extends SyncEntity {
public abstract class Unit extends SyncEntity implements SerializableEntity {
//total duration of hit effect
public static final float hitDuration = 9f;
@ -42,6 +46,32 @@ public abstract class Unit extends SyncEntity {
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(){
Tile tile = world.tileWorld(x, y);
return (Floor)(tile == null || (!(tile.floor() instanceof Floor)) ? Blocks.defaultFloor : tile.floor());

View file

@ -1,18 +1,19 @@
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.mindustry.entities.*;
import io.anuke.mindustry.game.Team;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import static io.anuke.mindustry.Vars.unitGroups;
public class BaseUnit extends Unit {
public class BaseUnit extends Unit{
public UnitType type;
public Timer timer = new Timer(5);
public float walkTime = 0f;
@ -109,6 +110,21 @@ public class BaseUnit extends Unit {
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
public void writeSpawn(ByteBuffer buffer) {
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.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.StorageBlocks;
import io.anuke.mindustry.entities.StatusEffect;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.entities.units.UnitType;
import io.anuke.mindustry.entities.SerializableEntity;
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.resource.Upgrade;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
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.Entity;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.util.Bits;
@ -48,6 +46,10 @@ public class Save16 extends SaveFileVersion {
float wavetime = stream.readFloat();
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
@ -62,71 +64,26 @@ public class Save16 extends SaveFileVersion {
map.put(id, Block.getByName(name));
}
float playerx = stream.readFloat();
float playery = stream.readFloat();
//entities
short playerhealth = stream.readShort();
byte peffect = stream.readByte();
float petime = stream.readFloat();
try {
if(!headless) {
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);
byte groups = stream.readByte();
//weapons
control.upgrades().getWeapons().clear();
control.upgrades().getWeapons().add(Weapons.blaster);
player.weaponLeft = player.weaponRight = Weapons.blaster;
int weapons = stream.readByte();
for (int i = 0; i < weapons; i++) {
control.upgrades().addWeapon(Upgrade.getByID(stream.readByte()));
for (int i = 0; i < groups; i++) {
int amount = stream.readInt();
byte gid = stream.readByte();
EntityGroup<?> group = Entities.getGroup(gid);
for (int j = 0; j < amount; j++) {
Entity entity = ClassReflection.newInstance(group.getType());
((SerializableEntity)entity).readSave(stream);
}
}
}else{
byte b = stream.readByte();
for(int i = 0; i < b; i ++) stream.readByte();
}catch (ReflectionException e){
throw new RuntimeException(e);
}
//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
short width = stream.readShort();
@ -204,42 +161,26 @@ public class Save16 extends SaveFileVersion {
stream.writeShort(block.id);
}
if(!headless) {
stream.writeFloat(player.x); //player x/y
stream.writeFloat(player.y);
//--ENTITIES--
//TODO synchronized block here
stream.writeShort((short)player.health); //player health
int groups = 0;
stream.writeByte(player.status.current().id); //status effect info
stream.writeFloat(player.status.getTime());
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
for(EntityGroup<?> group : Entities.getAllGroups()){
if(!group.isEmpty() && group.all().get(0) instanceof SerializableEntity){
groups ++;
}
}else{
stream.writeFloat(world.getSpawnX());
stream.writeFloat(world.getSpawnY());
stream.writeInt(150);
stream.writeByte(0);
}
//--ENEMIES--
stream.writeByte(Team.values().length); //amount of total teams (backwards compatibility)
stream.writeByte(groups);
for(Team team : Team.values()){
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
stream.writeInt(group.size()); //amount of units in the team group
for(BaseUnit unit : group.all()){
stream.writeByte(unit.type.id); //type
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());
for(EntityGroup<?> group : Entities.getAllGroups()){
if(!group.isEmpty() && group.all().get(0) instanceof SerializableEntity){
stream.writeInt(group.size());
stream.writeByte(group.getID());
for(Entity entity : group.all()){
((SerializableEntity)entity).writeSave(stream);
}
}
}

View file

@ -10,6 +10,7 @@ import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.Unit;
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.Layer;
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.ItemStack;
import io.anuke.mindustry.resource.Liquid;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Hue;
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.tilesize;
import static io.anuke.mindustry.Vars.world;
public class Block extends BaseBlock {
private static int lastid;
@ -240,6 +243,18 @@ public class Block extends BaseBlock {
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);
}