Batched building health update packet
This commit is contained in:
@@ -306,24 +306,26 @@ public class BlockIndexer{
|
|||||||
return breturnArray;
|
return breturnArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyBuildHealed(Building build){
|
public void notifyHealthChanged(Building build){
|
||||||
if(build.wasDamaged && !build.damaged() && damagedTiles[build.team.id] != null){
|
boolean damaged = build.damaged();
|
||||||
damagedTiles[build.team.id].remove(build);
|
|
||||||
build.wasDamaged = false;
|
if(build.wasDamaged != damaged){
|
||||||
|
if(damagedTiles[build.team.id] == null){
|
||||||
|
damagedTiles[build.team.id] = new Seq<>(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(damaged){
|
||||||
|
//is now damaged, add to array
|
||||||
|
damagedTiles[build.team.id].add(build);
|
||||||
|
}else{
|
||||||
|
//no longer damaged, remove
|
||||||
|
damagedTiles[build.team.id].remove(build);
|
||||||
|
}
|
||||||
|
|
||||||
|
build.wasDamaged = damaged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyBuildDamaged(Building build){
|
|
||||||
if(build.wasDamaged || !build.damaged()) return;
|
|
||||||
|
|
||||||
if(damagedTiles[build.team.id] == null){
|
|
||||||
damagedTiles[build.team.id] = new Seq<>(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
damagedTiles[build.team.id].add(build);
|
|
||||||
build.wasDamaged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void allBuildings(float x, float y, float range, Cons<Building> cons){
|
public void allBuildings(float x, float y, float range, Cons<Building> cons){
|
||||||
breturnArray.clear();
|
breturnArray.clear();
|
||||||
for(int i = 0; i < activeTeams.size; i++){
|
for(int i = 0; i < activeTeams.size; i++){
|
||||||
@@ -473,7 +475,7 @@ public class BlockIndexer{
|
|||||||
data.turretTree.insert(tile.build);
|
data.turretTree.insert(tile.build);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyBuildDamaged(tile.build);
|
notifyHealthChanged(tile.build);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(blocksPresent != null){
|
if(blocksPresent != null){
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class Liquids{
|
|||||||
gasColor = Color.valueOf("c1e8f5");
|
gasColor = Color.valueOf("c1e8f5");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
neoplasm = new CellLiquid("neoplasm", Color.valueOf("e05438")){{
|
neoplasm = new CellLiquid("neoplasm", Color.valueOf("c33e2b")){{
|
||||||
heatCapacity = 0.4f;
|
heatCapacity = 0.4f;
|
||||||
temperature = 0.54f;
|
temperature = 0.54f;
|
||||||
viscosity = 0.85f;
|
viscosity = 0.85f;
|
||||||
@@ -53,8 +53,8 @@ public class Liquids{
|
|||||||
hidden = true;
|
hidden = true;
|
||||||
spreadTarget = Liquids.water;
|
spreadTarget = Liquids.water;
|
||||||
|
|
||||||
colorFrom = Color.valueOf("f98f4a");
|
colorFrom = Color.valueOf("e8803f");
|
||||||
colorTo = Color.valueOf("9e172c");
|
colorTo = Color.valueOf("8c1225");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
arkycite = new Liquid("arkycite", Color.valueOf("84a94b")){{
|
arkycite = new Liquid("arkycite", Color.valueOf("84a94b")){{
|
||||||
|
|||||||
@@ -36,11 +36,12 @@ import static mindustry.Vars.*;
|
|||||||
public class NetServer implements ApplicationListener{
|
public class NetServer implements ApplicationListener{
|
||||||
/** note that snapshots are compressed, so the max snapshot size here is above the typical UDP safe limit */
|
/** note that snapshots are compressed, so the max snapshot size here is above the typical UDP safe limit */
|
||||||
private static final int maxSnapshotSize = 800;
|
private static final int maxSnapshotSize = 800;
|
||||||
private static final int timerBlockSync = 0;
|
private static final int timerBlockSync = 0, timerHealthSync = 1;
|
||||||
private static final float blockSyncTime = 60 * 6;
|
private static final float blockSyncTime = 60 * 6, healthSyncTime = 30;
|
||||||
private static final FloatBuffer fbuffer = FloatBuffer.allocate(20);
|
private static final FloatBuffer fbuffer = FloatBuffer.allocate(20);
|
||||||
private static final Writes dataWrites = new Writes(null);
|
private static final Writes dataWrites = new Writes(null);
|
||||||
private static final IntSeq hiddenIds = new IntSeq();
|
private static final IntSeq hiddenIds = new IntSeq();
|
||||||
|
private static final IntSeq healthSeq = new IntSeq(maxSnapshotSize / 4 + 1);
|
||||||
private static final Vec2 vector = new Vec2();
|
private static final Vec2 vector = new Vec2();
|
||||||
/** If a player goes away of their server-side coordinates by this distance, they get teleported back. */
|
/** If a player goes away of their server-side coordinates by this distance, they get teleported back. */
|
||||||
private static final float correctDist = tilesize * 14f;
|
private static final float correctDist = tilesize * 14f;
|
||||||
@@ -96,7 +97,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
};
|
};
|
||||||
|
|
||||||
private boolean closing = false;
|
private boolean closing = false;
|
||||||
private Interval timer = new Interval();
|
private Interval timer = new Interval(10);
|
||||||
|
private IntSet buildHealthChanged = new IntSet();
|
||||||
|
|
||||||
private ReusableByteOutStream writeBuffer = new ReusableByteOutStream(127);
|
private ReusableByteOutStream writeBuffer = new ReusableByteOutStream(127);
|
||||||
private Writes outputBuffer = new Writes(new DataOutputStream(writeBuffer));
|
private Writes outputBuffer = new Writes(new DataOutputStream(writeBuffer));
|
||||||
@@ -867,6 +869,11 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Queues a building health update. This will be sent in a Call.buildHealthUpdate packet later. */
|
||||||
|
public void buildHealthUpdate(Building build){
|
||||||
|
buildHealthChanged.add(build.pos());
|
||||||
|
}
|
||||||
|
|
||||||
/** Should only be used on the headless backend. */
|
/** Should only be used on the headless backend. */
|
||||||
public void openServer(){
|
public void openServer(){
|
||||||
try{
|
try{
|
||||||
@@ -1050,6 +1057,34 @@ public class NetServer implements ApplicationListener{
|
|||||||
if(Groups.player.size() > 0 && Core.settings.getBool("blocksync") && timer.get(timerBlockSync, blockSyncTime)){
|
if(Groups.player.size() > 0 && Core.settings.getBool("blocksync") && timer.get(timerBlockSync, blockSyncTime)){
|
||||||
writeBlockSnapshots();
|
writeBlockSnapshots();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Groups.player.size() > 0 && buildHealthChanged.size > 0 && timer.get(timerHealthSync, healthSyncTime)){
|
||||||
|
healthSeq.clear();
|
||||||
|
|
||||||
|
var iter = buildHealthChanged.iterator();
|
||||||
|
while(iter.hasNext){
|
||||||
|
int next = iter.next();
|
||||||
|
var build = world.build(next);
|
||||||
|
|
||||||
|
//pack pos + health into update list
|
||||||
|
if(build != null){
|
||||||
|
healthSeq.add(next, Float.floatToRawIntBits(build.health));
|
||||||
|
}
|
||||||
|
|
||||||
|
//if size exceeds snapshot limit, send it out and begin building it up again
|
||||||
|
if(healthSeq.size * 4 >= maxSnapshotSize){
|
||||||
|
Call.buildHealthUpdate(healthSeq);
|
||||||
|
healthSeq.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//send any residual health updates
|
||||||
|
if(healthSeq.size > 0){
|
||||||
|
Call.buildHealthUpdate(healthSeq);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildHealthChanged.clear();
|
||||||
|
}
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1762,13 +1762,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
@MethodPriority(100)
|
@MethodPriority(100)
|
||||||
@Override
|
@Override
|
||||||
public void heal(){
|
public void heal(){
|
||||||
indexer.notifyBuildHealed(self());
|
healthChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@MethodPriority(100)
|
@MethodPriority(100)
|
||||||
@Override
|
@Override
|
||||||
public void heal(float amount){
|
public void heal(float amount){
|
||||||
indexer.notifyBuildHealed(self());
|
healthChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1779,7 +1779,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
@Replace
|
@Replace
|
||||||
@Override
|
@Override
|
||||||
public void kill(){
|
public void kill(){
|
||||||
Call.tileDestroyed(self());
|
Call.buildDestroyed(self());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Replace
|
@Replace
|
||||||
@@ -1796,13 +1796,27 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
damage = Damage.applyArmor(damage, block.armor) / dm;
|
damage = Damage.applyArmor(damage, block.armor) / dm;
|
||||||
}
|
}
|
||||||
|
|
||||||
Call.tileDamage(self(), health - handleDamage(damage));
|
//TODO handle this better on the client.
|
||||||
|
if(!net.client()){
|
||||||
|
health -= handleDamage(damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
healthChanged();
|
||||||
|
|
||||||
if(health <= 0){
|
if(health <= 0){
|
||||||
Call.tileDestroyed(self());
|
Call.buildDestroyed(self());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void healthChanged(){
|
||||||
|
//server-side, health updates are batched.
|
||||||
|
if(net.server()){
|
||||||
|
netServer.buildHealthUpdate(self());
|
||||||
|
}
|
||||||
|
|
||||||
|
indexer.notifyHealthChanged(self());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double sense(LAccess sensor){
|
public double sense(LAccess sensor){
|
||||||
return switch(sensor){
|
return switch(sensor){
|
||||||
|
|||||||
@@ -84,14 +84,14 @@ public class RegionPart extends DrawPart{
|
|||||||
//can be null
|
//can be null
|
||||||
var region = drawRegion ? regions[Math.min(i, regions.length - 1)] : null;
|
var region = drawRegion ? regions[Math.min(i, regions.length - 1)] : null;
|
||||||
float sign = (i == 0 ? 1 : -1) * params.sideMultiplier;
|
float sign = (i == 0 ? 1 : -1) * params.sideMultiplier;
|
||||||
Tmp.v1.set((x + mx) * sign, y + my).rotateRadExact((params.rotation - 90) * Mathf.degRad);
|
Tmp.v1.set((x + mx) * sign * Draw.xscl, (y + my) * Draw.yscl).rotateRadExact((params.rotation - 90) * Mathf.degRad);
|
||||||
|
|
||||||
float
|
float
|
||||||
rx = params.x + Tmp.v1.x,
|
rx = params.x + Tmp.v1.x,
|
||||||
ry = params.y + Tmp.v1.y,
|
ry = params.y + Tmp.v1.y,
|
||||||
rot = mr * sign + params.rotation - 90;
|
rot = mr * sign + params.rotation - 90;
|
||||||
|
|
||||||
Draw.xscl = sign;
|
Draw.xscl *= sign;
|
||||||
|
|
||||||
if(outline && drawRegion){
|
if(outline && drawRegion){
|
||||||
Draw.z(prevZ + outlineLayerOffset);
|
Draw.z(prevZ + outlineLayerOffset);
|
||||||
@@ -115,7 +115,7 @@ public class RegionPart extends DrawPart{
|
|||||||
Drawf.additive(heat, heatColor.write(Tmp.c1).a(heatProgress.getClamp(params) * heatColor.a), rx, ry, rot, turretShading ? Layer.turretHeat : Draw.z() + heatLayerOffset);
|
Drawf.additive(heat, heatColor.write(Tmp.c1).a(heatProgress.getClamp(params) * heatColor.a), rx, ry, rot, turretShading ? Layer.turretHeat : Draw.z() + heatLayerOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.xscl = 1f;
|
Draw.xscl *= sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.z(z);
|
Draw.z(z);
|
||||||
|
|||||||
@@ -522,7 +522,7 @@ public class SectorDamage{
|
|||||||
other.build.addPlan(false);
|
other.build.addPlan(false);
|
||||||
other.remove();
|
other.remove();
|
||||||
}else{
|
}else{
|
||||||
indexer.notifyBuildDamaged(other.build);
|
indexer.notifyHealthChanged(other.build);
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(other.solid() && !other.synthetic()){ //skip damage propagation through solid blocks
|
}else if(other.solid() && !other.synthetic()){ //skip damage propagation through solid blocks
|
||||||
|
|||||||
@@ -709,20 +709,22 @@ public class Tile implements Position, QuadTreeObject, Displayable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, unreliable = true)
|
|
||||||
public static void tileDamage(Building build, float health){
|
|
||||||
if(build == null) return;
|
|
||||||
|
|
||||||
build.health = health;
|
|
||||||
|
|
||||||
if(build.damaged()){
|
|
||||||
indexer.notifyBuildDamaged(build);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(called = Loc.server)
|
@Remote(called = Loc.server)
|
||||||
public static void tileDestroyed(Building build){
|
public static void buildDestroyed(Building build){
|
||||||
if(build == null) return;
|
if(build == null) return;
|
||||||
build.killed();
|
build.killed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Remote
|
||||||
|
public static void buildHealthUpdate(IntSeq buildings){
|
||||||
|
for(int i = 0; i < buildings.size; i += 2){
|
||||||
|
int pos = buildings.items[i];
|
||||||
|
float health = Float.intBitsToFloat(buildings.items[i + 1]);
|
||||||
|
var build = world.build(pos);
|
||||||
|
if(build != null && build.health != health){
|
||||||
|
build.health = health;
|
||||||
|
indexer.notifyHealthChanged(build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,9 +89,7 @@ public class ConstructBlock extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//make sure block indexer knows it's damaged
|
//make sure block indexer knows it's damaged
|
||||||
if(tile.build.damaged()){
|
indexer.notifyHealthChanged(tile.build);
|
||||||
indexer.notifyBuildDamaged(tile.build);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//last builder was this local client player, call placed()
|
//last builder was this local client player, call placed()
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ org.gradle.caching=true
|
|||||||
#used for slow jitpack builds; TODO see if this actually works
|
#used for slow jitpack builds; TODO see if this actually works
|
||||||
org.gradle.internal.http.socketTimeout=100000
|
org.gradle.internal.http.socketTimeout=100000
|
||||||
org.gradle.internal.http.connectionTimeout=100000
|
org.gradle.internal.http.connectionTimeout=100000
|
||||||
archash=89f5cbe7ab
|
archash=123fbf12b9
|
||||||
|
|||||||
@@ -285,9 +285,6 @@ public class Generators{
|
|||||||
for(Block block : content.blocks()){
|
for(Block block : content.blocks()){
|
||||||
if(block.isAir() || block instanceof ConstructBlock || block instanceof OreBlock || block instanceof LegacyBlock) continue;
|
if(block.isAir() || block instanceof ConstructBlock || block instanceof OreBlock || block instanceof LegacyBlock) continue;
|
||||||
|
|
||||||
block.load();
|
|
||||||
block.loadIcon();
|
|
||||||
|
|
||||||
Seq<TextureRegion> toOutline = new Seq<>();
|
Seq<TextureRegion> toOutline = new Seq<>();
|
||||||
block.getRegionsToOutline(toOutline);
|
block.getRegionsToOutline(toOutline);
|
||||||
|
|
||||||
@@ -481,6 +478,37 @@ public class Generators{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
MultiPacker packer = new MultiPacker(){
|
||||||
|
@Override
|
||||||
|
public void add(PageType type, String name, PixmapRegion region, int[] splits, int[] pads){
|
||||||
|
String prefix = type == PageType.main ? "" : "../" + type.name() + "/";
|
||||||
|
Log.info("@ | @x@", prefix + name, region.width, region.height);
|
||||||
|
//save(region.pixmap, prefix + name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO !!!!! currently just an experiment
|
||||||
|
|
||||||
|
if(false)
|
||||||
|
generate("all-icons", () -> {
|
||||||
|
for(Seq<Content> arr : content.getContentMap()){
|
||||||
|
for(Content cont : arr){
|
||||||
|
if(cont instanceof UnlockableContent && !(cont instanceof Planet)){
|
||||||
|
UnlockableContent unlock = (UnlockableContent)cont;
|
||||||
|
|
||||||
|
if(unlock.generateIcons){
|
||||||
|
try{
|
||||||
|
unlock.createIcons(packer);
|
||||||
|
}catch(IllegalArgumentException e){
|
||||||
|
Log.err(e);
|
||||||
|
Log.err("Skip: @", unlock.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
generate("unit-icons", () -> content.units().each(type -> {
|
generate("unit-icons", () -> content.units().each(type -> {
|
||||||
if(type.internal) return; //internal hidden units don't generate
|
if(type.internal) return; //internal hidden units don't generate
|
||||||
|
|
||||||
@@ -488,9 +516,6 @@ public class Generators{
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
Unit sample = type.constructor.get();
|
Unit sample = type.constructor.get();
|
||||||
type.load();
|
|
||||||
type.loadIcon();
|
|
||||||
type.init();
|
|
||||||
|
|
||||||
Func<Pixmap, Pixmap> outline = i -> i.outline(type.outlineColor, 3);
|
Func<Pixmap, Pixmap> outline = i -> i.outline(type.outlineColor, 3);
|
||||||
Cons<TextureRegion> outliner = t -> {
|
Cons<TextureRegion> outliner = t -> {
|
||||||
@@ -703,7 +728,6 @@ public class Generators{
|
|||||||
|
|
||||||
generate("ore-icons", () -> {
|
generate("ore-icons", () -> {
|
||||||
content.blocks().<OreBlock>each(b -> b instanceof OreBlock, ore -> {
|
content.blocks().<OreBlock>each(b -> b instanceof OreBlock, ore -> {
|
||||||
ore.load();
|
|
||||||
int shadowColor = Color.rgba8888(0, 0, 0, 0.3f);
|
int shadowColor = Color.rgba8888(0, 0, 0, 0.3f);
|
||||||
|
|
||||||
for(int i = 0; i < ore.variants; i++){
|
for(int i = 0; i < ore.variants; i++){
|
||||||
|
|||||||
@@ -79,6 +79,11 @@ public class ImagePacker{
|
|||||||
return find(name);
|
return find(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PixmapRegion getPixmap(AtlasRegion region){
|
||||||
|
return new PixmapRegion(get(region.name));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean has(String s){
|
public boolean has(String s){
|
||||||
return cache.containsKey(s);
|
return cache.containsKey(s);
|
||||||
@@ -88,6 +93,7 @@ public class ImagePacker{
|
|||||||
Draw.scl = 1f / Core.atlas.find("scale_marker").width;
|
Draw.scl = 1f / Core.atlas.find("scale_marker").width;
|
||||||
|
|
||||||
Time.mark();
|
Time.mark();
|
||||||
|
Vars.content.load();
|
||||||
Generators.run();
|
Generators.run();
|
||||||
Log.info("&ly[Generator]&lc Total time to generate: &lg@&lcms", Time.elapsed());
|
Log.info("&ly[Generator]&lc Total time to generate: &lg@&lcms", Time.elapsed());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user