-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Minor optimizations for chunk retrieval
- Loading branch information
Showing
4 changed files
with
137 additions
and
0 deletions.
There are no files selected for viewing
65 changes: 65 additions & 0 deletions
65
src/main/java/org/embeddedt/vintagefix/chunk/VintageChunkMap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.embeddedt.vintagefix.chunk; | ||
|
||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; | ||
import net.minecraft.util.math.ChunkPos; | ||
import net.minecraft.world.chunk.Chunk; | ||
|
||
/** | ||
* This class implements a small LRU cache on top of Long2ObjectOpenHashMap to enable | ||
* faster chunk lookups if the same chunk is retrieved many times. | ||
*/ | ||
public class VintageChunkMap extends Long2ObjectOpenHashMap<Chunk> { | ||
private static final int CACHE_SIZE = 4; | ||
private final long[] cachedChunkPositions = new long[CACHE_SIZE]; | ||
private final Chunk[] cachedChunks = new Chunk[CACHE_SIZE]; | ||
|
||
public VintageChunkMap() { | ||
super(8192); | ||
} | ||
|
||
@Override | ||
public Chunk get(long key) { | ||
for (int i = 0; i < 4; ++i) { | ||
// Consolidate the scan into one comparison, allowing the JVM to better optimize the function | ||
// This is considerably faster than scanning two arrays side-by-side | ||
if (key == cachedChunkPositions[i]) { | ||
Chunk chunk = this.cachedChunks[i]; | ||
|
||
// If the chunk exists for the key, return the result | ||
// We also check that the position matches, in case mods try to access | ||
// chunks on the wrong thread | ||
if (chunk != null && ChunkPos.asLong(chunk.x, chunk.z) == key) { | ||
return chunk; | ||
} | ||
} | ||
} | ||
|
||
Chunk chunk = super.get(key); | ||
|
||
if (chunk != null) { | ||
this.addToCache(key, chunk); | ||
} | ||
|
||
return chunk; | ||
} | ||
|
||
@Override | ||
public Chunk remove(long k) { | ||
for (int i = 0; i < 4; ++i) { | ||
if (k == cachedChunkPositions[i]) { | ||
cachedChunks[i] = null; | ||
} | ||
} | ||
return super.remove(k); | ||
} | ||
|
||
private void addToCache(long key, Chunk chunk) { | ||
for (int i = CACHE_SIZE - 1; i > 0; --i) { | ||
this.cachedChunkPositions[i] = this.cachedChunkPositions[i - 1]; | ||
this.cachedChunks[i] = this.cachedChunks[i - 1]; | ||
} | ||
|
||
this.cachedChunkPositions[0] = key; | ||
this.cachedChunks[0] = chunk; | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/org/embeddedt/vintagefix/mixin/chunk_access/ChunkMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.embeddedt.vintagefix.mixin.chunk_access; | ||
|
||
import net.minecraft.block.state.IBlockState; | ||
import net.minecraft.init.Blocks; | ||
import net.minecraft.util.math.BlockPos; | ||
import net.minecraft.world.World; | ||
import net.minecraft.world.chunk.Chunk; | ||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; | ||
import org.spongepowered.asm.mixin.Final; | ||
import org.spongepowered.asm.mixin.Mixin; | ||
import org.spongepowered.asm.mixin.Overwrite; | ||
import org.spongepowered.asm.mixin.Shadow; | ||
|
||
@Mixin(Chunk.class) | ||
public class ChunkMixin { | ||
@Shadow | ||
@Final | ||
private ExtendedBlockStorage[] storageArrays; | ||
|
||
@Shadow | ||
@Final | ||
public static ExtendedBlockStorage NULL_BLOCK_STORAGE; | ||
|
||
private static final IBlockState DEFAULT_BLOCK_STATE = Blocks.AIR.getDefaultState(); | ||
|
||
/** | ||
* @reason Reduce method size to help the JVM inline | ||
* @author JellySquid | ||
*/ | ||
@Overwrite | ||
public IBlockState getBlockState(int x, int y, int z) { | ||
if (y >= 0 && (y >> 4) < this.storageArrays.length) { | ||
ExtendedBlockStorage section = this.storageArrays[y >> 4]; | ||
|
||
if (section != NULL_BLOCK_STORAGE) { | ||
return section.get(x & 15, y & 15, z & 15); | ||
} | ||
} | ||
|
||
return DEFAULT_BLOCK_STATE; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/org/embeddedt/vintagefix/mixin/chunk_access/ChunkProviderClientMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.embeddedt.vintagefix.mixin.chunk_access; | ||
|
||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; | ||
import net.minecraft.client.multiplayer.ChunkProviderClient; | ||
import net.minecraft.world.chunk.Chunk; | ||
import org.embeddedt.vintagefix.chunk.VintageChunkMap; | ||
import org.spongepowered.asm.mixin.Final; | ||
import org.spongepowered.asm.mixin.Mixin; | ||
import org.spongepowered.asm.mixin.Shadow; | ||
|
||
@Mixin(ChunkProviderClient.class) | ||
public class ChunkProviderClientMixin { | ||
@Shadow @Final private final Long2ObjectMap<Chunk> loadedChunks = new VintageChunkMap(); | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/org/embeddedt/vintagefix/mixin/chunk_access/ChunkProviderServerMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.embeddedt.vintagefix.mixin.chunk_access; | ||
|
||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; | ||
import net.minecraft.world.chunk.Chunk; | ||
import net.minecraft.world.gen.ChunkProviderServer; | ||
import org.embeddedt.vintagefix.chunk.VintageChunkMap; | ||
import org.spongepowered.asm.mixin.Final; | ||
import org.spongepowered.asm.mixin.Mixin; | ||
import org.spongepowered.asm.mixin.Shadow; | ||
|
||
@Mixin(ChunkProviderServer.class) | ||
public class ChunkProviderServerMixin { | ||
@Shadow | ||
@Final | ||
private final Long2ObjectMap<Chunk> loadedChunks = new VintageChunkMap(); | ||
} |