Skip to content

Commit 4afeb9b

Browse files
committed
optimizations
1 parent 6980753 commit 4afeb9b

File tree

15 files changed

+116
-41
lines changed

15 files changed

+116
-41
lines changed

dependency-reduced-pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
<dependency>
6464
<groupId>org.spigotmc</groupId>
6565
<artifactId>spigot-api</artifactId>
66-
<version>1.20.1-R0.1-SNAPSHOT</version>
66+
<version>1.21.8-R0.1-SNAPSHOT</version>
6767
<scope>provided</scope>
6868
</dependency>
6969
<dependency>

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
<dependency>
9696
<groupId>org.spigotmc</groupId>
9797
<artifactId>spigot-api</artifactId>
98-
<version>1.20.1-R0.1-SNAPSHOT</version>
98+
<version>1.21.8-R0.1-SNAPSHOT</version>
9999
<scope>provided</scope>
100100
</dependency>
101101

src/main/java/net/potato/tuff/TuffX.java

Lines changed: 110 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public void onEnable() {
7373
startProcessorTask();
7474
}
7575

76+
public record ChunkSectionCoord(int cx, int cy, int cz) {}
77+
7678
@Override
7779
public void onDisable() {
7880
if (processorTask != null) processorTask.cancel();
@@ -196,6 +198,7 @@ public void run() {
196198
if (world.isChunkLoaded(vec.getBlockX(), vec.getBlockZ())) {
197199
processAndSendChunk(player, world.getChunkAt(vec.getBlockX(), vec.getBlockZ()));
198200
} else {
201+
world.loadChunk(vec.getBlockX(), vec.getBlockZ(), true);
199202
queue.add(vec);
200203
}
201204
}
@@ -350,57 +353,125 @@ private byte[] createSectionPayload(ChunkSnapshot snapshot, int cx, int cz, int
350353

351354

352355
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
353-
public void onBlockBreak(BlockBreakEvent event) { if (event.getBlock().getY() < 0) sendBlockUpdateToNearby(event.getBlock().getLocation(), Material.AIR.createBlockData()); }
356+
public void onBlockBreak(BlockBreakEvent event) { if (event.getBlock().getY() < 0) handleBlockChange(event.getBlock().getLocation(), event.getBlock().getBlockData(), Material.AIR.createBlockData()); }
354357
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
355-
public void onBlockPlace(BlockPlaceEvent event) { if (event.getBlock().getY() < 0) sendBlockUpdateToNearby(event.getBlock().getLocation(), event.getBlock().getBlockData()); }
358+
public void onBlockPlace(BlockPlaceEvent event) { if (event.getBlock().getY() < 0) handleBlockChange(event.getBlock().getLocation(), event.getBlockReplacedState().getBlockData(), event.getBlock().getBlockData()); }
356359
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
357-
public void onBlockPhysics(BlockPhysicsEvent event) { if (event.getBlock().getY() < 0) sendBlockUpdateToNearby(event.getBlock().getLocation(), event.getBlock().getBlockData()); }
358-
359-
private void sendBlockUpdateToNearby(Location loc, BlockData data) {
360-
try {
361-
byte[] payload = createBlockUpdatePayload(loc, data);
362-
if (payload == null) return;
363-
for (Player p : loc.getWorld().getPlayers()) {
364-
if (p.getLocation().distanceSquared(loc) < 4096) p.sendPluginMessage(this, CHANNEL, payload);
365-
}
366-
} catch (IOException e) { getLogger().severe("Failed to send block update: " + e.getMessage()); }
360+
public void onBlockPhysics(BlockPhysicsEvent event) { Block block = event.getBlock(); if (block.getY() < 0) sendSingleBlockUpdate(block.getLocation(), block.getBlockData());sendLightingUpdate(block.getLocation()); }
361+
362+
private void sendSingleBlockUpdate(Location loc, BlockData data) {
363+
try (ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
364+
DataOutputStream out = new DataOutputStream(bout)) {
365+
366+
out.writeUTF("block_update");
367+
out.writeInt(loc.getBlockX());
368+
out.writeInt(loc.getBlockY());
369+
out.writeInt(loc.getBlockZ());
370+
371+
int[] legacyData = viablockids.toLegacy(data);
372+
out.writeShort((short) ((legacyData[1] << 12) | (legacyData[0] & 0xFFF)));
373+
374+
byte[] payload = bout.toByteArray();
375+
376+
new BukkitRunnable() {
377+
@Override
378+
public void run() {
379+
for (Player p : loc.getWorld().getPlayers()) {
380+
if (p.getLocation().distanceSquared(loc) < 4096) {
381+
p.sendPluginMessage(TuffX.this, CHANNEL, payload);
382+
}
383+
}
384+
}
385+
}.runTaskAsynchronously(this);
386+
387+
} catch (IOException e) {
388+
getLogger().severe("Failed to create single block update payload: " + e.getMessage());
389+
}
367390
}
368-
369-
private byte[] createBlockUpdatePayload(Location loc, BlockData data) throws IOException {
370-
Map<Location, Byte> lightUpdates = new HashMap<>();
371-
int radius = 16;
372-
World world = loc.getWorld();
373391

374-
for (int x = loc.getBlockX() - radius; x <= loc.getBlockX() + radius; x++) {
375-
for (int y = loc.getBlockY() - radius; y <= loc.getBlockY() + radius; y++) {
376-
for (int z = loc.getBlockZ() - radius; z <= loc.getBlockZ() + radius; z++) {
377-
if (y >= 0 || y < -64) continue;
392+
private void handleBlockChange(Location loc, BlockData oldData, BlockData newData) {
393+
sendSingleBlockUpdate(loc, newData);
394+
395+
boolean oldEmits = oldData.getLightEmission() > 0;
396+
boolean newEmits = newData.getLightEmission() > 0;
397+
boolean oldOccludes = oldData.getMaterial().isOccluding();
398+
boolean newOccludes = newData.getMaterial().isOccluding();
378399

379-
Block block = world.getBlockAt(x, y, z);
380-
int blockLight = block.getLightFromBlocks();
381-
int skyLight = block.getLightFromSky();
382-
byte packedLight = (byte) ((skyLight << 4) | blockLight);
400+
if (oldEmits != newEmits || oldOccludes != newOccludes) {
401+
sendLightingUpdate(loc);
402+
}
403+
}
404+
405+
private void sendLightingUpdate(Location loc) {
406+
Set<ChunkSectionCoord> sectionsToUpdate = new HashSet<>();
407+
World world = loc.getWorld();
408+
409+
for (int dx = -1; dx <= 1; dx++) {
410+
for (int dy = -1; dy <= 1; dy++) {
411+
for (int dz = -1; dz <= 1; dz++) {
412+
Location neighbor = loc.clone().add(dx, dy, dz);
413+
if (neighbor.getY() < -64 || neighbor.getY() >= 0) continue;
383414

384-
lightUpdates.put(new Location(world, x, y, z), packedLight);
415+
sectionsToUpdate.add(new ChunkSectionCoord(
416+
neighbor.getBlockX() >> 4,
417+
neighbor.getBlockY() >> 4,
418+
neighbor.getBlockZ() >> 4
419+
));
385420
}
386421
}
387422
}
388423

389-
try (ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(bout)) {
390-
out.writeUTF("block_update");
391-
out.writeInt(loc.getBlockX()); out.writeInt(loc.getBlockY()); out.writeInt(loc.getBlockZ());
392-
int[] legacyData = viablockids.toLegacy(data);
393-
out.writeShort((short) ((legacyData[1] << 12) | (legacyData[0] & 0xFFF)));
424+
for (ChunkSectionCoord sectionCoord : sectionsToUpdate) {
425+
ChunkSnapshot snapshot = world.getChunkAt(sectionCoord.cx, sectionCoord.cz).getChunkSnapshot(true, false, false);
394426

395-
out.writeInt(lightUpdates.size());
396-
for (Map.Entry<Location, Byte> entry : lightUpdates.entrySet()) {
397-
Location pos = entry.getKey();
398-
out.writeInt(pos.getBlockX());
399-
out.writeInt(pos.getBlockY());
400-
out.writeInt(pos.getBlockZ());
401-
out.writeByte(entry.getValue());
402-
}
427+
new BukkitRunnable() {
428+
@Override
429+
public void run() {
430+
try {
431+
byte[] payload = createLightingPayload(snapshot, sectionCoord);
432+
new BukkitRunnable() {
433+
@Override
434+
public void run() {
435+
for (Player p : world.getPlayers()) {
436+
if (p.getLocation().distanceSquared(loc) < 4096) {
437+
p.sendPluginMessage(TuffX.this, CHANNEL, payload);
438+
}
439+
}
440+
}
441+
}.runTask(TuffX.this);
442+
} catch (IOException e) {
443+
getLogger().severe("Failed to create lighting payload: " + e.getMessage());
444+
}
445+
}
446+
}.runTaskAsynchronously(this);
447+
}
448+
}
449+
450+
private byte[] createLightingPayload(ChunkSnapshot snapshot, ChunkSectionCoord section) throws IOException {
451+
try (ByteArrayOutputStream bout = new ByteArrayOutputStream(4120);
452+
DataOutputStream out = new DataOutputStream(bout)) {
453+
454+
out.writeUTF("lighting_update");
455+
out.writeInt(section.cx);
456+
out.writeInt(section.cz);
457+
out.writeInt(section.cy);
403458

459+
byte[] lightData = new byte[4096];
460+
int baseY = section.cy * 16;
461+
int i = 0;
462+
463+
for (int y = 0; y < 16; y++) {
464+
for (int z = 0; z < 16; z++) {
465+
for (int x = 0; x < 16; x++) {
466+
int worldY = baseY + y;
467+
int blockLight = snapshot.getBlockEmittedLight(x, worldY, z);
468+
int skyLight = snapshot.getBlockSkyLight(x, worldY, z);
469+
lightData[i++] = (byte) ((skyLight << 4) | blockLight);
470+
}
471+
}
472+
}
473+
474+
out.write(lightData);
404475
return bout.toByteArray();
405476
}
406477
}

target/TuffX.jar

4.67 KB
Binary file not shown.
0 Bytes
Binary file not shown.
54 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
1.44 KB
Binary file not shown.
1.42 KB
Binary file not shown.

0 commit comments

Comments
 (0)