Send destruction updates in batches to avoid network congestion

This commit is contained in:
Sollace 2021-01-27 18:03:35 +02:00
parent 0bde55a0fb
commit 8e89edfb35
3 changed files with 42 additions and 27 deletions

View file

@ -14,7 +14,7 @@ public class BlockDestructionManager {
public static final int UNSET_DAMAGE = -1;
public static final int MAX_DAMAGE = 10;
private final Destruction emptyDestruction = new Destruction(BlockPos.ORIGIN);
private final Destruction emptyDestruction = new Destruction();
private final World world;
@ -36,7 +36,7 @@ public class BlockDestructionManager {
public void setBlockDestruction(BlockPos pos, int amount) {
synchronized (locker) {
destructions.computeIfAbsent(pos.asLong(), p -> new Destruction(pos)).set(amount);
destructions.computeIfAbsent(pos.asLong(), p -> new Destruction()).set(amount);
}
}
@ -52,17 +52,25 @@ public class BlockDestructionManager {
public void tick() {
synchronized (locker) {
destructions.long2ObjectEntrySet().removeIf(entry -> entry.getValue().tick());
if (world instanceof ServerWorld) {
Long2ObjectMap<Integer> sent = new Long2ObjectOpenHashMap<>();
destructions.forEach((p, item) -> {
if (item.dirty) {
sent.put(p.longValue(), (Integer)item.amount);
}
});
if (!sent.isEmpty()) {
Channel.SERVER_BLOCK_DESTRUCTION.send(world, new MsgBlockDestruction(sent));
}
}
}
}
private class Destruction {
BlockPos pos;
int amount = -1;
int age = 50;
Destruction(BlockPos pos) {
this.pos = pos;
}
boolean dirty;
boolean tick() {
if (age-- > 0) {
@ -78,9 +86,7 @@ public class BlockDestructionManager {
void set(int amount) {
this.age = 50;
this.amount = amount >= 0 && amount < MAX_DAMAGE ? amount : UNSET_DAMAGE;
if (world instanceof ServerWorld) {
Channel.SERVER_BLOCK_DESTRUCTION.send(world, new MsgBlockDestruction(pos, this.amount));
}
this.dirty = true;
}
}

View file

@ -16,12 +16,12 @@ public class ClientBlockDestructionManager {
private final Object locker = new Object();
public void setBlockDestruction(BlockPos pos, int amount) {
public void setBlockDestruction(long pos, int amount) {
synchronized (locker) {
if (amount <= 0 || amount > BlockDestructionManager.MAX_DAMAGE) {
destructions.remove(pos.asLong());
destructions.remove(pos);
} else {
destructions.computeIfAbsent(pos.asLong(), p -> new Destruction(pos)).set(amount);
destructions.computeIfAbsent(pos, p -> new Destruction(pos)).set(amount);
}
}
}
@ -52,8 +52,8 @@ public class ClientBlockDestructionManager {
BlockBreakingInfo info;
Destruction(BlockPos pos) {
this.info = new BlockBreakingInfo(0, pos);
Destruction(long pos) {
this.info = new BlockBreakingInfo(0, BlockPos.fromLong(pos));
}
boolean tick() {

View file

@ -2,35 +2,44 @@ package com.minelittlepony.unicopia.network;
import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.fabricmc.fabric.api.network.PacketContext;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.BlockPos;
import net.minecraft.client.MinecraftClient;
public class MsgBlockDestruction implements Channel.Packet {
private final BlockPos pos;
private final int amount;
private final Long2ObjectMap<Integer> destructions;
MsgBlockDestruction(PacketByteBuf buffer) {
pos = buffer.readBlockPos();
amount = buffer.readByte();
destructions = new Long2ObjectOpenHashMap<>();
int size = buffer.readInt();
for (int i = 0; i < size; i++) {
destructions.put(buffer.readLong(), (Integer)buffer.readInt());
}
}
public MsgBlockDestruction(BlockPos pos, int amount) {
this.pos = pos;
this.amount = amount;
public MsgBlockDestruction(Long2ObjectMap<Integer> destructions) {
this.destructions = destructions;
}
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeBlockPos(pos);
buffer.writeByte(amount);
buffer.writeInt(destructions.size());
destructions.forEach((p, i) -> {
buffer.writeLong(p);
buffer.writeInt(i);
});
}
@Override
public void handle(PacketContext context) {
((ClientBlockDestructionManager.Source)MinecraftClient.getInstance().worldRenderer).getDestructionManager().setBlockDestruction(pos, amount);
ClientBlockDestructionManager destr = ((ClientBlockDestructionManager.Source)MinecraftClient.getInstance().worldRenderer).getDestructionManager();
destructions.forEach((i, d) -> {
destr.setBlockDestruction(i, d);
});
}
}