Compare commits
13 Commits
Build-scri
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c3b8e3239 | ||
|
|
b7527d1dba | ||
|
|
4d2519d0b0 | ||
|
|
47e8f5dae4 | ||
|
|
cff1a2d7fb | ||
|
|
a7e2207be5 | ||
|
|
a8ba53b243 | ||
|
|
e627088d55 | ||
|
|
2eef58a9e3 | ||
|
|
ff35e4a14b | ||
|
|
f4428b79a1 | ||
|
|
cd0007d17f | ||
|
|
0cdbe546b5 |
@@ -60,7 +60,7 @@
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.21.0.1</version>
|
||||
<version>3.41.2.2</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -262,4 +262,9 @@ public class AkarinGlobalConfig {
|
||||
private static void parallelMode() {
|
||||
parallelMode = getInt("core.parallel-mode", 1);
|
||||
}
|
||||
|
||||
public static boolean noChunksPastWorldBorder = true;
|
||||
private static void noChunksPastWorldBorder() {
|
||||
noChunksPastWorldBorder = getBoolean("core.no-chunks-past-world-border", noChunksPastWorldBorder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.akarin.server.mixin.core;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.server.BlockMinecartDetector;
|
||||
import net.minecraft.server.BlockPosition;
|
||||
import net.minecraft.server.IBlockData;
|
||||
import net.minecraft.server.World;
|
||||
|
||||
@Mixin(value = BlockMinecartDetector.class, remap = false)
|
||||
public abstract class MixinBlockMinecartDetector {
|
||||
@Inject(at = @At("HEAD"), method = "e", cancellable = true)
|
||||
private void e(World world, BlockPosition blockposition, IBlockData iblockdata, CallbackInfo ci) {
|
||||
if (iblockdata.getBlock() != (Object)this) ci.cancel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package io.akarin.server.mixin.core;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.server.EntityLiving;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.MathHelper;
|
||||
import net.minecraft.server.MobEffect;
|
||||
import net.minecraft.server.MobEffectList;
|
||||
import net.minecraft.server.MobEffects;
|
||||
|
||||
@Mixin(value = EntityLiving.class, remap = false)
|
||||
public abstract class MixinEntityLiving {
|
||||
@Shadow public abstract boolean hasEffect(MobEffectList mobeffectlist);
|
||||
@Shadow @Nullable public abstract MobEffect getEffect(MobEffectList mobeffectlist);
|
||||
@Shadow protected abstract float ct();
|
||||
protected long lastJumpTime = 0L; // Dionysus - Backport ArrowDMG fix
|
||||
|
||||
@Overwrite
|
||||
protected void cu() {
|
||||
// Dionysus start - Backport ArrowDMG fix
|
||||
long time = System.nanoTime();
|
||||
boolean canCrit = true;
|
||||
if ((Object)this instanceof EntityPlayer) {
|
||||
canCrit = false;
|
||||
if (time - lastJumpTime > (long)(0.250e9)) {
|
||||
lastJumpTime = time;
|
||||
canCrit = true;
|
||||
}
|
||||
}
|
||||
// Dionysus end - Backport ArrowDMG fix
|
||||
((EntityLiving)(Object)this).motY = (double) ct();
|
||||
if (hasEffect(MobEffects.JUMP)) {
|
||||
((EntityLiving)(Object)this).motY += (double) ((float) (getEffect(MobEffects.JUMP).getAmplifier() + 1) * 0.1F);
|
||||
}
|
||||
|
||||
if (canCrit&&((EntityLiving)(Object)this).isSprinting()) {
|
||||
float f = ((EntityLiving)(Object)this).yaw * 0.017453292F;
|
||||
|
||||
((EntityLiving)(Object)this).motX -= (double) (MathHelper.sin(f) * 0.2F);
|
||||
((EntityLiving)(Object)this).motZ += (double) (MathHelper.cos(f) * 0.2F);
|
||||
}
|
||||
|
||||
((EntityLiving)(Object)this).impulse = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package io.akarin.server.mixin.core;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import io.akarin.server.core.AkarinGlobalConfig;
|
||||
import net.minecraft.server.Chunk;
|
||||
import net.minecraft.server.ChunkCoordIntPair;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.PacketPlayOutMapChunk;
|
||||
import net.minecraft.server.PlayerChunk;
|
||||
import net.minecraft.server.PlayerChunkMap;
|
||||
import net.minecraft.server.WorldBorder;
|
||||
|
||||
@Mixin(value = PlayerChunk.class, remap = false)
|
||||
public abstract class MixinPlayerChunk {
|
||||
@Shadow @Final private static Logger a;
|
||||
@Shadow @Final private ChunkCoordIntPair location;
|
||||
@Shadow @Final private PlayerChunkMap playerChunkMap;
|
||||
@Shadow @Final public List<EntityPlayer> c;
|
||||
@Shadow public Chunk chunk;
|
||||
@Shadow private int dirtyCount;
|
||||
@Shadow private int h;
|
||||
@Shadow private long i;
|
||||
@Shadow private boolean done;
|
||||
|
||||
@Shadow public abstract void sendChunk(EntityPlayer entityplayer);
|
||||
|
||||
@Overwrite
|
||||
public void a(final EntityPlayer entityplayer) { // CraftBukkit - added final to argument
|
||||
if (this.c.contains(entityplayer)) {
|
||||
a.debug("Failed to add player. {} already is in chunk {}, {}", entityplayer, Integer.valueOf(this.location.x), Integer.valueOf(this.location.z));
|
||||
return;
|
||||
}
|
||||
if (AkarinGlobalConfig.noChunksPastWorldBorder) {
|
||||
WorldBorder worldborder = playerChunkMap.getWorld().getWorldBorder();
|
||||
int centerchunkx = ((int)worldborder.getCenterX()) >> 4;
|
||||
int centerchunkz = ((int)worldborder.getCenterZ()) >> 4;
|
||||
int sizechunks = ((int)worldborder.getSize()) >> 5;
|
||||
++sizechunks;
|
||||
if(location.x<centerchunkx - sizechunks||location.x>=centerchunkx + sizechunks||location.z<centerchunkz - sizechunks||location.z>=centerchunkz + sizechunks) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.c.isEmpty()) {
|
||||
this.i = this.playerChunkMap.getWorld().getTime();
|
||||
}
|
||||
|
||||
this.c.add(entityplayer);
|
||||
|
||||
if (this.done) {
|
||||
this.sendChunk(entityplayer);
|
||||
}
|
||||
}
|
||||
|
||||
@Overwrite
|
||||
public boolean b() {
|
||||
if (this.done) {
|
||||
return true;
|
||||
}
|
||||
if (this.chunk == null) {
|
||||
return false;
|
||||
}
|
||||
if (!this.chunk.isReady()) {
|
||||
return false;
|
||||
}
|
||||
if (!this.chunk.world.chunkPacketBlockController.onChunkPacketCreate(this.chunk, '\uffff', false)) { // Paper - Anti-Xray - Load nearby chunks if necessary
|
||||
return false;
|
||||
}
|
||||
this.dirtyCount = 0;
|
||||
this.h = 0;
|
||||
this.done = true;
|
||||
if (c.isEmpty()) return true; // Akarin - Fixes MC-120780
|
||||
PacketPlayOutMapChunk packetplayoutmapchunk = new PacketPlayOutMapChunk(this.chunk, '\uffff');
|
||||
Iterator<EntityPlayer> iterator = this.c.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
EntityPlayer entityplayer = iterator.next();
|
||||
|
||||
entityplayer.playerConnection.sendPacket(packetplayoutmapchunk);
|
||||
this.playerChunkMap.getWorld().getTracker().a(entityplayer, this.chunk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.akarin.server.mixin.core;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import net.minecraft.server.EntityHuman;
|
||||
import net.minecraft.server.TileEntityLootable;
|
||||
|
||||
@Mixin(value = TileEntityLootable.class, remap = false)
|
||||
public abstract class MixinTileEntityLootable {
|
||||
@Inject(at = @At("HEAD"), method = "b(Lnet/minecraft/server/EntityHuman;Lorg/spongepowered/asm/mixin/injection/callback/CallbackInfo;)V", cancellable = true)
|
||||
private void b(EntityHuman entityhuman, CallbackInfo ci) {
|
||||
if (entityhuman == null) ci.cancel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.akarin.server.mixin.core;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.server.BlockPosition;
|
||||
import net.minecraft.server.WorldBorder;
|
||||
|
||||
@Mixin(value = WorldBorder.class, remap = false)
|
||||
public abstract class MixinWorldBorder {
|
||||
@Shadow
|
||||
public abstract boolean isInBounds(BlockPosition blockposition);
|
||||
|
||||
@Overwrite
|
||||
public boolean isBlockInBounds(int chunkX, int chunkZ) {
|
||||
BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); // Dionysus - avoid collisions with other threads
|
||||
mutPos.setValues(chunkX, 64, chunkZ);
|
||||
return isInBounds(mutPos);
|
||||
}
|
||||
|
||||
@Overwrite
|
||||
public boolean isChunkInBounds(int chunkX, int chunkZ) {
|
||||
BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); // Dionysus - avoid collisions with other threads // threads
|
||||
mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15);
|
||||
return isInBounds(mutPos);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package io.akarin.server.mixin.optimization;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.server.DataBits;
|
||||
|
||||
@Mixin(value = DataBits.class, remap = false)
|
||||
public abstract class MixinDataBits {
|
||||
@Shadow @Final private long[] a;
|
||||
@Shadow @Final private int b;
|
||||
@Shadow @Final private long c;
|
||||
|
||||
@Overwrite
|
||||
public void a(int i, int j) {
|
||||
int k = i * this.b;
|
||||
int l = k >> 6;
|
||||
int i1 = (i + 1) * this.b - 1 >> 6;
|
||||
int j1 = k ^ l << 6;
|
||||
|
||||
this.a[l] = this.a[l] & ~(this.c << j1) | ((long) j & this.c) << j1;
|
||||
if (l != i1) {
|
||||
int k1 = 64 - j1;
|
||||
int l1 = this.b - k1;
|
||||
|
||||
this.a[i1] = this.a[i1] >>> l1 << l1 | ((long) j & this.c) >> k1;
|
||||
}
|
||||
|
||||
}
|
||||
@Overwrite
|
||||
public int a(int i) {
|
||||
int j = i * this.b;
|
||||
int k = j >> 6;
|
||||
int l = (i + 1) * this.b - 1 >> 6;
|
||||
int i1 = j ^ k << 6;
|
||||
|
||||
if (k == l) {
|
||||
return (int) (this.a[k] >>> i1 & this.c);
|
||||
} else {
|
||||
int j1 = 64 - i1;
|
||||
|
||||
return (int) ((this.a[k] >>> i1 | this.a[l] << j1) & this.c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,6 @@ import org.bukkit.event.entity.EntityPortalEvent;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
// CraftBukkit end
|
||||
|
||||
// Dionysus start
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
// Dionysus end
|
||||
|
||||
/**
|
||||
* Akarin Changes Note
|
||||
* 1) Random -> LightRandom (performance)
|
||||
@@ -95,7 +91,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
||||
private static int entityCount = 1; // Paper - MC-111480 - ID 0 is treated as special for DataWatchers, start 1
|
||||
private int id;
|
||||
public boolean i; public boolean blocksEntitySpawning() { return i; } // Paper - OBFHELPER
|
||||
public final ObjectArrayList<Entity> passengers; // Dionysus
|
||||
public final List<Entity> passengers;
|
||||
protected int j;
|
||||
private Entity au;public void setVehicle(Entity entity) { this.au = entity; } // Paper // OBFHELPER
|
||||
public boolean attachedToPlayer;
|
||||
@@ -209,7 +205,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
||||
|
||||
public Entity(World world) {
|
||||
this.id = Entity.entityCount++;
|
||||
this.passengers = new ObjectArrayList<>(); // Dionysus
|
||||
this.passengers = Lists.newArrayList();
|
||||
this.boundingBox = Entity.c;
|
||||
this.width = 0.6F;
|
||||
this.length = 1.8F;
|
||||
@@ -2885,7 +2881,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
|
||||
}
|
||||
|
||||
public List<Entity> bF() {
|
||||
return (List) (this.passengers.isEmpty() ? Collections.emptyList() : new ObjectArrayList<>(this.passengers)); // Dionysus
|
||||
return (List) (this.passengers.isEmpty() ? Collections.emptyList() : Lists.newArrayList(this.passengers));
|
||||
}
|
||||
|
||||
public boolean w(Entity entity) {
|
||||
|
||||
@@ -1,314 +0,0 @@
|
||||
package net.minecraft.server;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
// CraftBukkit Start
|
||||
import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor;
|
||||
// CraftBukkit end
|
||||
|
||||
/**
|
||||
* Akarin Changes Note
|
||||
* 1) Check whether players empty (performance, MC-120780)
|
||||
*/
|
||||
public class PlayerChunk {
|
||||
|
||||
private static final Logger a = LogManager.getLogger();
|
||||
private final PlayerChunkMap playerChunkMap;
|
||||
public final List<EntityPlayer> c = Lists.newArrayList(); // CraftBukkit - public
|
||||
private final ChunkCoordIntPair location;
|
||||
private final short[] dirtyBlocks = new short[64];
|
||||
@Nullable
|
||||
public Chunk chunk; // CraftBukkit - public
|
||||
private int dirtyCount;
|
||||
private int h;
|
||||
private long i;
|
||||
private boolean done;
|
||||
|
||||
// CraftBukkit start - add fields
|
||||
boolean chunkExists; // Paper
|
||||
private boolean loadInProgress = false;
|
||||
private Runnable loadedRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadInProgress = false;
|
||||
PlayerChunk.this.chunk = PlayerChunk.this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(location.x, location.z);
|
||||
markChunkUsed(); // Paper - delay chunk unloads
|
||||
}
|
||||
};
|
||||
// Paper start - delay chunk unloads
|
||||
public final void markChunkUsed() {
|
||||
if (chunk != null && chunk.scheduledForUnload != null) {
|
||||
chunk.scheduledForUnload = null;
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
// CraftBukkit end
|
||||
|
||||
public PlayerChunk(PlayerChunkMap playerchunkmap, int i, int j) {
|
||||
this.playerChunkMap = playerchunkmap;
|
||||
this.location = new ChunkCoordIntPair(i, j);
|
||||
// CraftBukkit start
|
||||
loadInProgress = true;
|
||||
this.chunk = playerchunkmap.getWorld().getChunkProviderServer().getChunkAt(i, j, loadedRunnable, false);
|
||||
this.chunkExists = this.chunk != null || ChunkIOExecutor.hasQueuedChunkLoad(playerChunkMap.getWorld(), i, j); // Paper
|
||||
markChunkUsed(); // Paper - delay chunk unloads
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
public ChunkCoordIntPair a() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public void a(final EntityPlayer entityplayer) { // CraftBukkit - added final to argument
|
||||
if (this.c.contains(entityplayer)) {
|
||||
PlayerChunk.a.debug("Failed to add player. {} already is in chunk {}, {}", entityplayer, Integer.valueOf(this.location.x), Integer.valueOf(this.location.z));
|
||||
} else {
|
||||
if (this.c.isEmpty()) {
|
||||
this.i = this.playerChunkMap.getWorld().getTime();
|
||||
}
|
||||
|
||||
this.c.add(entityplayer);
|
||||
// CraftBukkit start - use async chunk io
|
||||
// if (this.done) {
|
||||
// this.sendChunk(entityplayer);
|
||||
// }
|
||||
if (this.done) {
|
||||
this.sendChunk(entityplayer);
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void b(EntityPlayer entityplayer) {
|
||||
if (this.c.contains(entityplayer)) {
|
||||
// CraftBukkit start - If we haven't loaded yet don't load the chunk just so we can clean it up
|
||||
if (!this.done) {
|
||||
this.c.remove(entityplayer);
|
||||
|
||||
if (this.c.isEmpty()) {
|
||||
ChunkIOExecutor.dropQueuedChunkLoad(this.playerChunkMap.getWorld(), this.location.x, this.location.z, this.loadedRunnable);
|
||||
this.playerChunkMap.b(this);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (this.done) {
|
||||
entityplayer.playerConnection.sendPacket(new PacketPlayOutUnloadChunk(this.location.x, this.location.z));
|
||||
}
|
||||
|
||||
this.c.remove(entityplayer);
|
||||
if (this.c.isEmpty()) {
|
||||
this.playerChunkMap.b(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public boolean a(boolean flag) {
|
||||
if (this.chunk != null) {
|
||||
return true;
|
||||
} else {
|
||||
/* CraftBukkit start
|
||||
if (flag) {
|
||||
this.chunk = this.playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(this.location.x, this.location.z);
|
||||
} else {
|
||||
this.chunk = this.playerChunkMap.getWorld().getChunkProviderServer().getOrLoadChunkAt(this.location.x, this.location.z);
|
||||
}
|
||||
*/
|
||||
if (!loadInProgress) {
|
||||
loadInProgress = true;
|
||||
this.chunk = playerChunkMap.getWorld().getChunkProviderServer().getChunkAt(this.location.x, this.location.z, loadedRunnable, flag);
|
||||
markChunkUsed(); // Paper - delay chunk unloads
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
return this.chunk != null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean b() {
|
||||
if (this.done) {
|
||||
return true;
|
||||
} else if (this.chunk == null) {
|
||||
return false;
|
||||
} else if (!this.chunk.isReady()) {
|
||||
return false;
|
||||
} else if (!this.chunk.world.chunkPacketBlockController.onChunkPacketCreate(this.chunk, '\uffff', false)) { // Paper - Anti-Xray - Load nearby chunks if necessary
|
||||
return false; // Paper - Anti-Xray - Wait and try again later
|
||||
} else {
|
||||
this.dirtyCount = 0;
|
||||
this.h = 0;
|
||||
this.done = true;
|
||||
if (c.isEmpty()) return true; // Akarin - Fixes MC-120780
|
||||
PacketPlayOutMapChunk packetplayoutmapchunk = new PacketPlayOutMapChunk(this.chunk, '\uffff');
|
||||
Iterator iterator = this.c.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
|
||||
|
||||
entityplayer.playerConnection.sendPacket(packetplayoutmapchunk);
|
||||
this.playerChunkMap.getWorld().getTracker().a(entityplayer, this.chunk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendChunk(EntityPlayer entityplayer) {
|
||||
if (this.done) {
|
||||
this.chunk.world.chunkPacketBlockController.onChunkPacketCreate(this.chunk, '\uffff', true); // Paper - Anti-Xray - Load nearby chunks if necessary
|
||||
entityplayer.playerConnection.sendPacket(new PacketPlayOutMapChunk(this.chunk, '\uffff'));
|
||||
this.playerChunkMap.getWorld().getTracker().a(entityplayer, this.chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public void c() {
|
||||
long i = this.playerChunkMap.getWorld().getTime();
|
||||
|
||||
if (this.chunk != null) {
|
||||
this.chunk.c(this.chunk.x() + i - this.i);
|
||||
}
|
||||
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public void a(int i, int j, int k) {
|
||||
if (this.done) {
|
||||
if (this.dirtyCount == 0) {
|
||||
this.playerChunkMap.a(this);
|
||||
}
|
||||
|
||||
this.h |= 1 << (j >> 4);
|
||||
if (this.dirtyCount < 64) {
|
||||
short short0 = (short) (i << 12 | k << 8 | j);
|
||||
|
||||
for (int l = 0; l < this.dirtyCount; ++l) {
|
||||
if (this.dirtyBlocks[l] == short0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.dirtyBlocks[this.dirtyCount++] = short0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void a(Packet<?> packet) {
|
||||
if (this.done) {
|
||||
for (int i = 0; i < this.c.size(); ++i) {
|
||||
this.c.get(i).playerConnection.sendPacket(packet);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void d() {
|
||||
if (this.done && this.chunk != null) {
|
||||
if (this.dirtyCount != 0) {
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
|
||||
if (this.dirtyCount == 1) {
|
||||
i = (this.dirtyBlocks[0] >> 12 & 15) + this.location.x * 16;
|
||||
j = this.dirtyBlocks[0] & 255;
|
||||
k = (this.dirtyBlocks[0] >> 8 & 15) + this.location.z * 16;
|
||||
BlockPosition blockposition = new BlockPosition(i, j, k);
|
||||
|
||||
this.a((new PacketPlayOutBlockChange(this.playerChunkMap.getWorld(), blockposition)));
|
||||
if (this.playerChunkMap.getWorld().getType(blockposition).getBlock().isTileEntity()) {
|
||||
this.a(this.playerChunkMap.getWorld().getTileEntity(blockposition));
|
||||
}
|
||||
} else if (this.dirtyCount == 64) {
|
||||
// Paper - Anti-Xray - Loading chunks here could cause a ConcurrentModificationException #1104
|
||||
//this.chunk.world.chunkPacketBlockController.onChunkPacketCreate(this.chunk, this.h, true); // Paper - Anti-Xray - Load nearby chunks if necessary
|
||||
this.a((new PacketPlayOutMapChunk(this.chunk, this.h)));
|
||||
} else {
|
||||
this.a((new PacketPlayOutMultiBlockChange(this.dirtyCount, this.dirtyBlocks, this.chunk)));
|
||||
|
||||
for (i = 0; i < this.dirtyCount; ++i) {
|
||||
j = (this.dirtyBlocks[i] >> 12 & 15) + this.location.x * 16;
|
||||
k = this.dirtyBlocks[i] & 255;
|
||||
int l = (this.dirtyBlocks[i] >> 8 & 15) + this.location.z * 16;
|
||||
BlockPosition blockposition1 = new BlockPosition(j, k, l);
|
||||
|
||||
if (this.playerChunkMap.getWorld().getType(blockposition1).getBlock().isTileEntity()) {
|
||||
this.a(this.playerChunkMap.getWorld().getTileEntity(blockposition1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.dirtyCount = 0;
|
||||
this.h = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void a(@Nullable TileEntity tileentity) {
|
||||
if (tileentity != null) {
|
||||
PacketPlayOutTileEntityData packetplayouttileentitydata = tileentity.getUpdatePacket();
|
||||
|
||||
if (packetplayouttileentitydata != null) {
|
||||
this.a(packetplayouttileentitydata);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean d(EntityPlayer entityplayer) {
|
||||
return this.c.contains(entityplayer);
|
||||
}
|
||||
|
||||
public boolean a(Predicate<EntityPlayer> predicate) {
|
||||
return Iterables.tryFind(this.c, predicate).isPresent();
|
||||
}
|
||||
|
||||
public boolean a(double d0, Predicate<EntityPlayer> predicate) {
|
||||
int i = 0;
|
||||
|
||||
for (int j = this.c.size(); i < j; ++i) {
|
||||
EntityPlayer entityplayer = this.c.get(i);
|
||||
|
||||
if (predicate.apply(entityplayer) && this.location.a(entityplayer) < d0 * d0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean e() {
|
||||
return this.done;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Chunk f() {
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
public double g() {
|
||||
double d0 = Double.MAX_VALUE;
|
||||
Iterator iterator = this.c.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
|
||||
double d1 = this.location.a(entityplayer);
|
||||
|
||||
if (d1 < d0) {
|
||||
d0 = d1;
|
||||
}
|
||||
}
|
||||
|
||||
return d0;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@
|
||||
"core.MixinMinecraftServer",
|
||||
"core.MixinChunkIOExecutor",
|
||||
"core.MixinPlayerConnectionUtils",
|
||||
"core.MixinPlayerChunk",
|
||||
"core.MixinWorldBorder",
|
||||
"core.MixinEntityLiving",
|
||||
"core.MixinTileEntityLootable",
|
||||
"core.MixinBlockMinecartDetector",
|
||||
|
||||
"nsc.OptimisticNetworkManager",
|
||||
"nsc.NonblockingServerConnection",
|
||||
@@ -44,6 +49,7 @@
|
||||
"optimization.MixinContainerHorse",
|
||||
"optimization.MixinExplosion",
|
||||
"optimization.MixinMathHelper",
|
||||
"optimization.MixinBlockStationary"
|
||||
"optimization.MixinBlockStationary",
|
||||
"optimization.MixinDataBits"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user