minimize client world class
This commit is contained in:
parent
eec61c9258
commit
76e018b4ed
62 changed files with 1183 additions and 1338 deletions
|
@ -23,6 +23,7 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
@ -97,17 +98,20 @@ import client.window.Wheel;
|
|||
import client.window.Window;
|
||||
import client.window.WindowEvent;
|
||||
import client.world.ChunkClient;
|
||||
import client.world.WorldClient;
|
||||
import client.world.ChunkEmpty;
|
||||
import common.Version;
|
||||
import common.block.Block;
|
||||
import common.collect.Lists;
|
||||
import common.collect.Maps;
|
||||
import common.collect.Sets;
|
||||
import common.color.TextColor;
|
||||
import common.dimension.Dimension;
|
||||
import common.dimension.Space;
|
||||
import common.effect.Effect;
|
||||
import common.effect.StatusEffect;
|
||||
import common.entity.Entity;
|
||||
import common.entity.animal.EntityHorse;
|
||||
import common.entity.item.EntityCart;
|
||||
import common.entity.npc.Energy;
|
||||
import common.entity.npc.EntityCpu;
|
||||
import common.entity.npc.EntityNPC;
|
||||
|
@ -152,18 +156,25 @@ import common.packet.CPacketMessage;
|
|||
import common.packet.HPacketHandshake;
|
||||
import common.packet.CPacketAction.Action;
|
||||
import common.properties.Property;
|
||||
import common.rng.Random;
|
||||
import common.sound.EventType;
|
||||
import common.sound.MovingSoundMinecart;
|
||||
import common.sound.PositionedSound;
|
||||
import common.tileentity.TileEntity;
|
||||
import common.util.BlockPos;
|
||||
import common.util.BoundingBox;
|
||||
import common.util.CharValidator;
|
||||
import common.util.ChunkPos;
|
||||
import common.util.ExtMath;
|
||||
import common.util.Facing;
|
||||
import common.util.HitPosition;
|
||||
import common.util.IntHashMap;
|
||||
import common.util.LongHashMap;
|
||||
import common.util.ParticleType;
|
||||
import common.util.Util;
|
||||
import common.util.Var;
|
||||
import common.util.HitPosition.ObjectType;
|
||||
import common.vars.Vars;
|
||||
import common.world.Chunk;
|
||||
import common.world.LightType;
|
||||
import common.world.State;
|
||||
import common.world.World;
|
||||
|
@ -270,6 +281,92 @@ public class Client implements IThreadListener {
|
|||
|
||||
private record DebugFunction(Keysym key, DebugRunner runner, String help) {
|
||||
}
|
||||
|
||||
private final class WorldClient extends World {
|
||||
public WorldClient(Dimension dim) {
|
||||
super(dim, true);
|
||||
this.calculateInitialSkylight();
|
||||
this.calculateInitialWeather();
|
||||
this.updatePhysics();
|
||||
}
|
||||
|
||||
public boolean spawnEntityInWorld(Entity entityIn) {
|
||||
boolean flag = super.spawnEntityInWorld(entityIn);
|
||||
Client.this.spawnEntityInWorld(flag, entityIn);
|
||||
return flag;
|
||||
}
|
||||
|
||||
public void removeEntity(Entity entityIn) {
|
||||
super.removeEntity(entityIn);
|
||||
Client.this.removeEntity(entityIn);
|
||||
}
|
||||
|
||||
protected void onEntityAdded(Entity entityIn) {
|
||||
Client.this.onEntityAdded(entityIn);
|
||||
}
|
||||
|
||||
protected void onEntityRemoved(Entity entityIn) {
|
||||
Client.this.onEntityRemoved(entityIn);
|
||||
}
|
||||
|
||||
public Entity getEntityByID(int id) {
|
||||
return id == Client.this.player.getId() ? Client.this.player : super.getEntityByID(id);
|
||||
}
|
||||
|
||||
public void playSound(double x, double y, double z, SoundEvent sound, float volume) {
|
||||
Client.this.getSoundManager().playSound(new PositionedSound(sound, volume, (float)x, (float)y, (float)z));
|
||||
}
|
||||
|
||||
public Chunk getChunk(int x, int z) {
|
||||
return Client.this.getChunk(x, z);
|
||||
}
|
||||
|
||||
public Chunk getChunk(BlockPos pos) {
|
||||
return Client.this.getChunk(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
}
|
||||
|
||||
protected float getTemperature(BlockPos pos) {
|
||||
if(!isValid(pos))
|
||||
return 0.0f;
|
||||
ChunkClient chunk = Client.this.getChunk(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
return pos.getY() > 64 ? chunk.getTemperature(pos) - (chunk.getOffset(pos) + (float)pos.getY() - 64.0F) / 15.0f : chunk.getTemperature(pos);
|
||||
}
|
||||
|
||||
protected boolean isLoaded(int x, int z, boolean allowEmpty) {
|
||||
return allowEmpty || !Client.this.getChunk(x, z).isDummy();
|
||||
}
|
||||
|
||||
public void spawnParticle(ParticleType particle, double xCoord, double yCoord, double zCoord, int data) {
|
||||
Client.this.effectRenderer.spawnParticle(Client.this.getRenderViewEntity(), particle, xCoord, yCoord, zCoord, data);
|
||||
}
|
||||
|
||||
public void playAuxSFX(EntityNPC player, int sfxType, BlockPos blockPosIn, int data) {
|
||||
if(Client.this.getNetHandler() != null)
|
||||
Client.this.getNetHandler().playAuxSFX(sfxType, blockPosIn, data);
|
||||
}
|
||||
|
||||
public void markBlockForUpdate(BlockPos pos) {
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
Client.this.renderGlobal.markBlocksForUpdate(x - 1, y - 1, z - 1, x + 1, y + 1, z + 1);
|
||||
}
|
||||
|
||||
public void notifyLightSet(BlockPos pos) {
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
Client.this.renderGlobal.markBlocksForUpdate(x - 1, y - 1, z - 1, x + 1, y + 1, z + 1);
|
||||
}
|
||||
|
||||
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {
|
||||
Client.this.renderGlobal.markBlocksForUpdate(x1 - 1, y1 - 1, z1 - 1, x2 + 1, y2 + 1, z2 + 1);
|
||||
}
|
||||
|
||||
public void setLastLightning(int last, int color) {
|
||||
Client.this.entityRenderer.setLastLightning(last, color);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String VERSION = Version.NAME + " Client " + Util.VERSION;
|
||||
public static final int LOG_BUFFER = 32768;
|
||||
|
@ -295,6 +392,13 @@ public class Client implements IThreadListener {
|
|||
private final long[] frames = new long[240];
|
||||
public final Map<String, Integer> playerList = Maps.<String, Integer>newTreeMap();
|
||||
public final List<PlayerCharacter> characterList = Lists.<PlayerCharacter>newArrayList();
|
||||
private final Set<Entity> entityList = Sets.<Entity>newHashSet();
|
||||
private final Set<Entity> spawnQueue = Sets.<Entity>newHashSet();
|
||||
private final Set<ChunkPos> previousActive = Sets.<ChunkPos>newHashSet();
|
||||
private final LongHashMap<ChunkClient> chunkMapping = new LongHashMap();
|
||||
private final List<ChunkClient> chunkListing = Lists.<ChunkClient>newArrayList();
|
||||
private final Set<Long> emptyChunkListing = Sets.<Long>newHashSet();
|
||||
private final Set<Long> nextEmptyChunkListing = Sets.<Long>newHashSet();
|
||||
|
||||
private boolean primary;
|
||||
private boolean secondary;
|
||||
|
@ -410,12 +514,19 @@ public class Client implements IThreadListener {
|
|||
private AudioInterface audio;
|
||||
private String buffer = "";
|
||||
public PlayerController controller;
|
||||
public WorldClient world;
|
||||
public World world;
|
||||
public EntityNPC player;
|
||||
public HitPosition pointed;
|
||||
public DisplayMode vidMode;
|
||||
public String dimensionName;
|
||||
public String message;
|
||||
private ChunkClient emptyChunk;
|
||||
private ChunkClient outsideChunk;
|
||||
|
||||
private List<Entity> entities;
|
||||
private List<Entity> unloaded;
|
||||
private List<TileEntity> tiles;
|
||||
private IntHashMap<Entity> entityIds;
|
||||
|
||||
|
||||
@Variable(name = "chunk_view_distance", category = CVarCategory.RENDER, min = 2, max = 16, callback = DistanceFunction.class, display = "Sichtweite", unit = "Chunks")
|
||||
|
@ -484,7 +595,7 @@ public class Client implements IThreadListener {
|
|||
@Variable(name = "draw_rain_particle_range", category = CVarCategory.RENDER, min = 0, max = 25, display = "Regen-Partikel-Radius")
|
||||
public int rainParticleRange = 10;
|
||||
@Variable(name = "draw_void_particles", category = CVarCategory.RENDER, display = "Partikel in der Tiefe")
|
||||
public boolean voidParticles = true;
|
||||
private boolean voidParticles = true;
|
||||
@Variable(name = "draw_void_fog", category = CVarCategory.RENDER, display = "Nebel in der Tiefe")
|
||||
public boolean voidFog = true;
|
||||
@Variable(name = "crosshair_size", category = CVarCategory.GUI, min = 0, max = 32, display = "Größe des Fadenkreuzes")
|
||||
|
@ -601,8 +712,7 @@ public class Client implements IThreadListener {
|
|||
this.debugWorld = true;
|
||||
this.charEditor = false;
|
||||
this.controller = new PlayerController(this, player);
|
||||
WorldClient world = new WorldClient(this, Space.INSTANCE);
|
||||
this.loadWorld(world, EntityRegistry.getEntityID(EntityCpu.class));
|
||||
this.loadWorld(Space.INSTANCE, EntityRegistry.getEntityID(EntityCpu.class));
|
||||
this.player.setId(0);
|
||||
this.show(null);
|
||||
this.player.flying = true;
|
||||
|
@ -620,6 +730,7 @@ public class Client implements IThreadListener {
|
|||
this.viewEntity = null;
|
||||
this.connection = null;
|
||||
this.world = null;
|
||||
this.resetWorld();
|
||||
this.player = null;
|
||||
this.serverInfo = null;
|
||||
this.lastTickTime = -1;
|
||||
|
@ -865,21 +976,20 @@ public class Client implements IThreadListener {
|
|||
if (this.chunkLoadTimer == 30)
|
||||
{
|
||||
this.chunkLoadTimer = 0;
|
||||
this.world.ensureAreaLoaded(this.player);
|
||||
this.ensureAreaLoaded(this.player);
|
||||
}
|
||||
}
|
||||
this.entityRenderer.updateRenderer();
|
||||
this.renderGlobal.updateClouds();
|
||||
this.world.decrLightning();
|
||||
this.world.updateEntities();
|
||||
}
|
||||
this.soundManager.update();
|
||||
if (this.world != null)
|
||||
{
|
||||
this.world.tick();
|
||||
this.tickWorld();
|
||||
if (this.world != null)
|
||||
{
|
||||
this.world.displayTick(ExtMath.floord(this.player.posX), ExtMath.floord(this.player.posY), ExtMath.floord(this.player.posZ));
|
||||
this.displayTick(ExtMath.floord(this.player.posX), ExtMath.floord(this.player.posY), ExtMath.floord(this.player.posZ));
|
||||
}
|
||||
this.effectRenderer.update();
|
||||
}
|
||||
|
@ -1209,7 +1319,7 @@ public class Client implements IThreadListener {
|
|||
if(this.cameraUsed) {
|
||||
this.cameraUsed = false;
|
||||
if(this.world != null)
|
||||
this.world.setLastLightning(1, 0xffffff);
|
||||
this.entityRenderer.setLastLightning(1, 0xffffff);
|
||||
}
|
||||
if(this.isDirty())
|
||||
this.save();
|
||||
|
@ -1489,12 +1599,18 @@ public class Client implements IThreadListener {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadWorld(WorldClient world, int type)
|
||||
public World loadWorld(Dimension dim, int type)
|
||||
{
|
||||
this.resetWorld();
|
||||
this.viewEntity = null;
|
||||
this.connection = null;
|
||||
this.soundManager.stopSounds();
|
||||
this.world = world;
|
||||
this.world = new WorldClient(dim);
|
||||
this.entities = this.world.entities;
|
||||
this.unloaded = this.world.unloaded;
|
||||
this.tiles = this.world.tiles;
|
||||
this.entityIds = this.world.entityIds;
|
||||
this.initWorld();
|
||||
|
||||
if (this.renderGlobal != null)
|
||||
{
|
||||
|
@ -1517,11 +1633,12 @@ public class Client implements IThreadListener {
|
|||
this.viewEntity = this.player;
|
||||
|
||||
System.gc();
|
||||
return this.world;
|
||||
}
|
||||
|
||||
public void setDimensionAndSpawnPlayer(int type)
|
||||
{
|
||||
this.world.removeAllEntities();
|
||||
this.removeAllEntities();
|
||||
int i = 0;
|
||||
|
||||
if (this.player != null)
|
||||
|
@ -1694,18 +1811,14 @@ public class Client implements IThreadListener {
|
|||
String mem = String.format("JVM-Speicher: %d%% %d/%dMB", usedMem * 100L / maxMem, usedMem / 1024L / 1024L, maxMem / 1024L / 1024L)
|
||||
+ "\n" +
|
||||
String.format("JVM-Reserviert: %d%% %dMB", totalMem * 100L / maxMem, totalMem / 1024L / 1024L);
|
||||
if(this.world == null) {
|
||||
if(this.world == null)
|
||||
return mem;
|
||||
}
|
||||
|
||||
BlockPos blockpos = new BlockPos(this.viewEntity.posX, this.viewEntity.getEntityBoundingBox().minY,
|
||||
this.viewEntity.posZ);
|
||||
|
||||
Entity entity = this.viewEntity;
|
||||
Facing facing = entity.getHorizontalFacing();
|
||||
String dirStr = "Ungültig";
|
||||
switch(facing) {
|
||||
BlockPos pos = new BlockPos(this.viewEntity.posX, this.viewEntity.getEntityBoundingBox().minY, this.viewEntity.posZ);
|
||||
String dirStr;
|
||||
switch(this.viewEntity.getHorizontalFacing()) {
|
||||
case NORTH:
|
||||
default:
|
||||
dirStr = "Norden (Nach negativer Z)";
|
||||
break;
|
||||
case SOUTH:
|
||||
|
@ -1718,28 +1831,7 @@ public class Client implements IThreadListener {
|
|||
dirStr = "Osten (Nach positiver X)";
|
||||
break;
|
||||
}
|
||||
|
||||
String bline;
|
||||
String lline;
|
||||
if(this.world.isBlockLoaded(blockpos)) {
|
||||
ChunkClient chunk = this.world.getChunk(blockpos);
|
||||
bline = String.format("Biom: %.2f K, N: %.2f K, D: %s (%s)", chunk.getTemperature(blockpos), chunk.getOffset(blockpos),
|
||||
TextColor.stripCodes(this.world.dimension.getDisplay()),
|
||||
this.dimensionName == null ? UniverseRegistry.getName(this.world.dimension) : this.dimensionName);
|
||||
lline = "Licht: " + chunk.getLightSub(blockpos, 0) + " (" + chunk.getLight(LightType.SKY, blockpos) + " Himmel, "
|
||||
+ chunk.getLight(LightType.BLOCK, blockpos) + " Blöcke, " + String.format(
|
||||
"%.1f", this.world.getSunBrightness(1.0f) * 15.0f) + " Welt), A: "
|
||||
+ String.format("%.1f °", this.world.getCelestialAngle(1.0f));
|
||||
}
|
||||
else {
|
||||
bline = "Biom: <?>, D: " +
|
||||
TextColor.stripCodes(this.world.dimension.getDisplay()) +
|
||||
" (" + (this.dimensionName == null ? UniverseRegistry.getName(this.world.dimension) : this.dimensionName) + ")";
|
||||
lline = "Licht: " + String.format(
|
||||
"%.1f", this.world.getSunBrightness(1.0f) * 15.0f) + " Welt, A: "
|
||||
+ String.format("%.1f °", this.world.getCelestialAngle(1.0f));
|
||||
}
|
||||
|
||||
ChunkClient chunk = this.getChunk(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
long ticked = System.currentTimeMillis() - this.lastTicked;
|
||||
|
||||
return
|
||||
|
@ -1750,21 +1842,26 @@ public class Client implements IThreadListener {
|
|||
// this.connected != null ? this.connected : "[???]"))),
|
||||
this.renderGlobal.getDebugInfoRenders() + "\n" +
|
||||
this.renderGlobal.getDebugInfoEntities() + "\n" +
|
||||
"Partikel: " + this.effectRenderer.getParticleCount() + ". O: " + this.world.getDebugLoadedEntities() + "\n" +
|
||||
this.world.getInfo() + "\n" +
|
||||
"Partikel: " + this.effectRenderer.getParticleCount() + ". O: " + this.entities.size() + "\n" +
|
||||
"Chunk-Cache: M " + this.chunkMapping.getNumHashElements() + ", L " + this.chunkListing.size() + "\n" +
|
||||
String.format("XYZ: %.3f / %.3f / %.3f", this.viewEntity.posX,
|
||||
this.viewEntity.getEntityBoundingBox().minY, this.viewEntity.posZ) + "\n" +
|
||||
String.format("Block: %d %d %d, R: '%s/%s'", blockpos.getX(), blockpos.getY(), blockpos.getZ(),
|
||||
Util.getRegionFolder(blockpos.getX() >> 4, blockpos.getZ() >> 4),
|
||||
Util.getRegionName(blockpos.getX() >> 4, blockpos.getZ() >> 4)) + "\n" +
|
||||
String.format("Chunk: %d %d %d + %d %d %d, FOV: %.1f °%s", blockpos.getX() >> 4, blockpos.getY() >> 4, blockpos.getZ() >> 4,
|
||||
blockpos.getX() & 15, blockpos.getY() & 15, blockpos.getZ() & 15, this.zooming ?
|
||||
String.format("Block: %d %d %d, R: '%s/%s'", pos.getX(), pos.getY(), pos.getZ(),
|
||||
Util.getRegionFolder(pos.getX() >> 4, pos.getZ() >> 4),
|
||||
Util.getRegionName(pos.getX() >> 4, pos.getZ() >> 4)) + "\n" +
|
||||
String.format("Chunk: %d %d %d + %d %d %d, FOV: %.1f °%s", pos.getX() >> 4, pos.getY() >> 4, pos.getZ() >> 4,
|
||||
pos.getX() & 15, pos.getY() & 15, pos.getZ() & 15, this.zooming ?
|
||||
(this.fov / this.zoomLevel) : this.fov, this.zooming ?
|
||||
String.format(" (Zoom x%.1f)", this.zoomLevel) : "") + "\n" +
|
||||
String.format("Richtung: %s (%.1f / %.1f)", dirStr,
|
||||
ExtMath.wrapf(entity.rotYaw), ExtMath.wrapf(entity.rotPitch)) + "\n" +
|
||||
bline + "\n" +
|
||||
lline + "\n" +
|
||||
ExtMath.wrapf(this.viewEntity.rotYaw), ExtMath.wrapf(this.viewEntity.rotPitch)) + "\n" +
|
||||
String.format("Biom: %.2f K, N: %.2f K, D: %s (%s)", chunk.getTemperature(pos), chunk.getOffset(pos),
|
||||
TextColor.stripCodes(this.world.dimension.getDisplay()),
|
||||
this.dimensionName == null ? UniverseRegistry.getName(this.world.dimension) : this.dimensionName) + "\n" +
|
||||
"Licht: " + chunk.getLightSub(pos, 0) + " (" + chunk.getLight(LightType.SKY, pos) + " Himmel, "
|
||||
+ chunk.getLight(LightType.BLOCK, pos) + " Blöcke, " + String.format(
|
||||
"%.1f", this.entityRenderer.getSunBrightness(1.0f) * 15.0f) + " Welt), A: "
|
||||
+ String.format("%.1f °", this.world.getCelestialAngle(1.0f)) + "\n" +
|
||||
String.format("Zeit: %d T, R %d / %d T, U %d / %d T",
|
||||
this.world.getDayTime(),
|
||||
this.world.getDayTime() % this.world.dimension.getRotationalPeriod(),
|
||||
|
@ -1774,8 +1871,8 @@ public class Client implements IThreadListener {
|
|||
) + "\n" +
|
||||
String.format("Laub: %s%s, T: %.2f K / %.2f °C, %s (R %.1f, %.1f)",
|
||||
!this.world.dimension.hasSeasons() ? "*" : "",
|
||||
this.world.getLeavesGen(blockpos).getDisplayName(),
|
||||
this.world.getTemperatureK(blockpos), this.world.getTemperatureC(blockpos),
|
||||
this.world.getLeavesGen(pos).getDisplayName(),
|
||||
this.world.getTemperatureK(pos), this.world.getTemperatureC(pos),
|
||||
this.world.getWeather().getDisplay(), this.world.getRainStrength(),
|
||||
this.world.getDarkness()
|
||||
) + "\n" +
|
||||
|
@ -3225,6 +3322,348 @@ public class Client implements IThreadListener {
|
|||
}
|
||||
}
|
||||
|
||||
private void displayTick(int posX, int posY, int posZ) {
|
||||
int range = 16;
|
||||
Random rand = new Random();
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||
for(int n = 0; n < 1000; n++) {
|
||||
int x = posX + rand.zrange(range) - rand.zrange(range);
|
||||
int y = posY + rand.zrange(range) - rand.zrange(range);
|
||||
int z = posZ + rand.zrange(range) - rand.zrange(range);
|
||||
pos.set(x, y, z);
|
||||
State state = this.world.getState(pos);
|
||||
state.getBlock().displayTick(this.world, pos, state, rand);
|
||||
}
|
||||
if(this.world.dimension.hasVoidFog() && this.voidParticles && posY < 32) {
|
||||
for(int n = 0; n < 1000; n++) {
|
||||
float x = ((float)posX) + (rand.floatv() - rand.floatv() - 0.5f) * 32.0f;
|
||||
float y = (posY < -32 ? (float)posY - 32.0f : -64.0f) + rand.floatv() * 65.0f;
|
||||
float z = ((float)posZ) + (rand.floatv() - rand.floatv() - 0.5f) * 32.0f;
|
||||
if(y < -64.0f || rand.floatv() >= (64.0f + y) / 64.0f)
|
||||
this.world.spawnParticle(ParticleType.DEPTH, (double)x, (double)y, (double)z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initWorld() {
|
||||
this.emptyChunk = new ChunkEmpty(this.world, false, this.debugWorld);
|
||||
this.outsideChunk = new ChunkEmpty(this.world, true, this.debugWorld);
|
||||
}
|
||||
|
||||
private void resetWorld() {
|
||||
this.entityList.clear();
|
||||
this.spawnQueue.clear();
|
||||
this.previousActive.clear();
|
||||
this.chunkMapping.clear();
|
||||
this.chunkListing.clear();
|
||||
this.emptyChunkListing.clear();
|
||||
this.nextEmptyChunkListing.clear();
|
||||
this.emptyChunk = null;
|
||||
this.outsideChunk = null;
|
||||
this.entityRenderer.resetLightning();
|
||||
this.entities = null;
|
||||
this.unloaded = null;
|
||||
this.tiles = null;
|
||||
this.entityIds = null;
|
||||
}
|
||||
|
||||
public ChunkClient getChunk(int x, int z) {
|
||||
ChunkClient chunk = this.chunkMapping.getValueByKey(LongHashMap.packInt(x, z));
|
||||
return chunk == null ? this.getEmptyChunk(x, z) : chunk;
|
||||
}
|
||||
|
||||
private ChunkClient getEmptyChunk(int x, int z) {
|
||||
int size = this.world.dimension.getSize() / 16;
|
||||
return x < -size || z < -size || x >= size || z >= size ? this.outsideChunk : this.emptyChunk;
|
||||
}
|
||||
|
||||
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {
|
||||
this.renderGlobal.markBlocksForUpdate(x1 - 1, y1 - 1, z1 - 1, x2 + 1, y2 + 1, z2 + 1);
|
||||
}
|
||||
|
||||
private void markReload(int cx, int cz, int range) {
|
||||
this.nextEmptyChunkListing.clear();
|
||||
for(int x = cx - range; x <= cx + range; x++) {
|
||||
for(int z = cz - range; z <= cz + range; z++) {
|
||||
long id = LongHashMap.packInt(x, z);
|
||||
if(this.chunkMapping.getValueByKey(id) != null) {
|
||||
if(this.emptyChunkListing.contains(id)) {
|
||||
this.emptyChunkListing.remove(id);
|
||||
this.nextEmptyChunkListing.add(id);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
this.chunkMapping.add(id, this.getEmptyChunk(x, z));
|
||||
this.emptyChunkListing.remove(id);
|
||||
this.nextEmptyChunkListing.add(id);
|
||||
this.markBlockRangeForRenderUpdate(x << 4, -World.MAX_SIZE_Y, z << 4, (x << 4) + 15, World.MAX_SIZE_Y, (z << 4) + 15);
|
||||
}
|
||||
}
|
||||
for(Long id : this.emptyChunkListing) {
|
||||
this.chunkMapping.remove(id);
|
||||
int x = LongHashMap.getX(id);
|
||||
int z = LongHashMap.getZ(id);
|
||||
this.markBlockRangeForRenderUpdate(x << 4, -World.MAX_SIZE_Y, z << 4, (x << 4) + 15, World.MAX_SIZE_Y, (z << 4) + 15);
|
||||
}
|
||||
this.emptyChunkListing.clear();
|
||||
this.emptyChunkListing.addAll(this.nextEmptyChunkListing);
|
||||
}
|
||||
|
||||
public void markReload() {
|
||||
if(this.player != null && !this.charEditor)
|
||||
this.markReload((int)this.player.posX >> 4, (int)this.player.posZ >> 4, this.renderDistance + 4);
|
||||
}
|
||||
|
||||
public void setExterminated(boolean exterminated) {
|
||||
this.world.dimension.setExterminated(exterminated);
|
||||
this.initWorld();
|
||||
this.markReload();
|
||||
for(Long id : this.emptyChunkListing) {
|
||||
int x = LongHashMap.getX(id);
|
||||
int z = LongHashMap.getZ(id);
|
||||
this.chunkMapping.add(id, this.getEmptyChunk(x, z));
|
||||
this.markBlockRangeForRenderUpdate(x << 4, -World.MAX_SIZE_Y, z << 4, (x << 4) + 15, World.MAX_SIZE_Y, (z << 4) + 15);
|
||||
}
|
||||
}
|
||||
|
||||
private void tickWorld()
|
||||
{
|
||||
this.world.updatePhysics();
|
||||
this.markReload();
|
||||
|
||||
if (Vars.dayCycle)
|
||||
{
|
||||
this.world.setDayTime(this.world.getDayTime() + (long)Vars.timeFlow);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10 && !this.spawnQueue.isEmpty(); ++i)
|
||||
{
|
||||
Entity entity = (Entity)this.spawnQueue.iterator().next();
|
||||
this.spawnQueue.remove(entity);
|
||||
|
||||
if (!this.entities.contains(entity))
|
||||
{
|
||||
this.world.spawnEntityInWorld(entity);
|
||||
}
|
||||
}
|
||||
long time = System.currentTimeMillis();
|
||||
for (ChunkClient chunk : this.chunkListing)
|
||||
{
|
||||
chunk.update(System.currentTimeMillis() - time > 5L);
|
||||
}
|
||||
if (System.currentTimeMillis() - time > 100L)
|
||||
{
|
||||
Log.TICK.warn("Render-Chunk-Tick dauerte " + (System.currentTimeMillis() - time) + " ms");
|
||||
}
|
||||
|
||||
Set<ChunkPos> active = this.world.setActivePlayerChunksAndCheckLight(this.renderDistance);
|
||||
this.previousActive.retainAll(active);
|
||||
|
||||
if (this.previousActive.size() == active.size())
|
||||
{
|
||||
this.previousActive.clear();
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (ChunkPos chunkcoordintpair : active)
|
||||
{
|
||||
if (!this.previousActive.contains(chunkcoordintpair))
|
||||
{
|
||||
int j = chunkcoordintpair.x * 16;
|
||||
int k = chunkcoordintpair.z * 16;
|
||||
ChunkClient chunk = this.getChunk(chunkcoordintpair.x, chunkcoordintpair.z);
|
||||
chunk.enqueueRelight();
|
||||
this.previousActive.add(chunkcoordintpair);
|
||||
++i;
|
||||
|
||||
if (i >= 10)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doPreChunk(int x, int z, boolean load)
|
||||
{
|
||||
long id = LongHashMap.packInt(x, z);
|
||||
if (load)
|
||||
{
|
||||
if(this.chunkMapping.getValueByKey(id) != null)
|
||||
this.doPreChunk(x, z, false);
|
||||
ChunkClient chunk = new ChunkClient(this.world, x, z);
|
||||
this.chunkMapping.add(id, chunk);
|
||||
this.chunkListing.add(chunk);
|
||||
chunk.setLoaded();
|
||||
}
|
||||
else
|
||||
{
|
||||
ChunkClient chunk = this.getChunk(x, z);
|
||||
chunk.onChunkUnload();
|
||||
this.chunkMapping.remove(id);
|
||||
this.chunkListing.remove(chunk);
|
||||
this.emptyChunkListing.remove(id);
|
||||
}
|
||||
|
||||
if (!load)
|
||||
{
|
||||
this.markBlockRangeForRenderUpdate(x * 16, -World.MAX_SIZE_Y, z * 16, x * 16 + 15, World.MAX_SIZE_Y, z * 16 + 15);
|
||||
}
|
||||
}
|
||||
|
||||
public void addEntityToWorld(int entityID, Entity entityToSpawn)
|
||||
{
|
||||
Entity entity = this.world.getEntityByID(entityID);
|
||||
|
||||
if (entity != null)
|
||||
{
|
||||
this.world.removeEntity(entity);
|
||||
}
|
||||
|
||||
this.entityList.add(entityToSpawn);
|
||||
entityToSpawn.setId(entityID);
|
||||
|
||||
if (!this.world.spawnEntityInWorld(entityToSpawn))
|
||||
{
|
||||
this.spawnQueue.add(entityToSpawn);
|
||||
}
|
||||
|
||||
this.entityIds.addKey(entityID, entityToSpawn);
|
||||
}
|
||||
|
||||
public Entity removeEntityFromWorld(int entityID)
|
||||
{
|
||||
Entity entity = this.entityIds.removeObject(entityID);
|
||||
|
||||
if (entity != null)
|
||||
{
|
||||
this.entityList.remove(entity);
|
||||
this.world.removeEntity(entity);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void removeAllEntities()
|
||||
{
|
||||
this.entities.removeAll(this.unloaded);
|
||||
|
||||
for (int i = 0; i < this.unloaded.size(); ++i)
|
||||
{
|
||||
Entity entity = this.unloaded.get(i);
|
||||
int j = entity.chunkCoordX;
|
||||
int k = entity.chunkCoordZ;
|
||||
|
||||
if (entity.addedToChunk)
|
||||
{
|
||||
this.getChunk(j, k).removeEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
for (int l = 0; l < this.unloaded.size(); ++l)
|
||||
{
|
||||
this.onEntityRemoved(this.unloaded.get(l));
|
||||
}
|
||||
|
||||
this.unloaded.clear();
|
||||
|
||||
for (int i1 = 0; i1 < this.entities.size(); ++i1)
|
||||
{
|
||||
Entity entity1 = this.entities.get(i1);
|
||||
|
||||
if (entity1.vehicle != null)
|
||||
{
|
||||
if (!entity1.vehicle.dead && entity1.vehicle.passenger == entity1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entity1.vehicle.passenger = null;
|
||||
entity1.vehicle = null;
|
||||
}
|
||||
|
||||
if (entity1.dead)
|
||||
{
|
||||
int j1 = entity1.chunkCoordX;
|
||||
int k1 = entity1.chunkCoordZ;
|
||||
|
||||
if (entity1.addedToChunk)
|
||||
{
|
||||
this.getChunk(j1, k1).removeEntity(entity1);
|
||||
}
|
||||
|
||||
this.entities.remove(i1--);
|
||||
this.onEntityRemoved(entity1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnEntityInWorld(boolean flag, Entity entityIn)
|
||||
{
|
||||
this.entityList.add(entityIn);
|
||||
if (!flag)
|
||||
{
|
||||
this.spawnQueue.add(entityIn);
|
||||
}
|
||||
else if (entityIn instanceof EntityCart)
|
||||
{
|
||||
this.soundManager.playSound(new MovingSoundMinecart((EntityCart)entityIn));
|
||||
}
|
||||
}
|
||||
|
||||
private void removeEntity(Entity entityIn)
|
||||
{
|
||||
this.entityList.remove(entityIn);
|
||||
}
|
||||
|
||||
private void onEntityAdded(Entity entityIn)
|
||||
{
|
||||
if (this.spawnQueue.contains(entityIn))
|
||||
{
|
||||
this.spawnQueue.remove(entityIn);
|
||||
}
|
||||
}
|
||||
|
||||
private void onEntityRemoved(Entity entityIn)
|
||||
{
|
||||
boolean flag = false;
|
||||
|
||||
if (this.entityList.contains(entityIn))
|
||||
{
|
||||
if (entityIn.isEntityAlive())
|
||||
{
|
||||
this.spawnQueue.add(entityIn);
|
||||
flag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.entityList.remove(entityIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureAreaLoaded(Entity entity) {
|
||||
int x = ExtMath.floord(entity.posX / 16.0D);
|
||||
int z = ExtMath.floord(entity.posZ / 16.0D);
|
||||
int r = 2;
|
||||
for(int cx = x - r; cx <= x + r; ++cx) {
|
||||
for(int cz = z - r; cz <= z + r; ++cz) {
|
||||
this.getChunk(cx, cz);
|
||||
}
|
||||
}
|
||||
if(!this.entities.contains(entity))
|
||||
this.entities.add(entity);
|
||||
}
|
||||
|
||||
public List<Entity> getEntities() {
|
||||
return this.entities;
|
||||
}
|
||||
|
||||
public List<TileEntity> getTiles() {
|
||||
return this.tiles;
|
||||
}
|
||||
|
||||
private static byte[] genTriwave(int w, int h, int color1, int color2, int color3, int color4, int color5, int color6) {
|
||||
byte[] data = new byte[w * h * 4];
|
||||
byte[] color = new byte[24];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue