diff options
12 files changed, 275 insertions, 393 deletions
diff --git a/src/main/java/makamys/lodmod/LODMod.java b/src/main/java/makamys/lodmod/LODMod.java index ab4fb07..e018832 100644 --- a/src/main/java/makamys/lodmod/LODMod.java +++ b/src/main/java/makamys/lodmod/LODMod.java @@ -1,29 +1,19 @@ package makamys.lodmod; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.Blocks; -import net.minecraft.launchwrapper.Launch; -import net.minecraft.util.MathHelper; -import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.WorldEvent; -import java.nio.IntBuffer; - -import org.lwjgl.BufferUtils; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL12; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; -import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import makamys.lodmod.renderer.MyRenderer; +import makamys.lodmod.util.SpriteUtil; @Mod(modid = LODMod.MODID, version = LODMod.VERSION) public class LODMod @@ -31,14 +21,45 @@ public class LODMod public static final String MODID = "lodmod"; public static final String VERSION = "0.0"; + public static final Logger LOGGER = LogManager.getLogger("lodmod"); + + public static MyRenderer renderer; + @EventHandler public void init(FMLInitializationEvent event) { FMLCommonHandler.instance().bus().register(this); + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Load event) { + if(!event.world.isRemote) return; + + SpriteUtil.init(); + if(renderer != null) { + LOGGER.warn("Renderer didn't get destroyed last time"); + renderer.destroy(); + } + renderer = new MyRenderer(); } @SubscribeEvent - public void onClientTick(ClientTickEvent event) { + public void onWorldUnload(WorldEvent.Unload event) { + if(!event.world.isRemote) return; + renderer.destroy(); + renderer = null; + } + + public static boolean isActive() { + return renderer != null; + } + + @SubscribeEvent + public void onWorldUnload(TickEvent.ServerTickEvent event) { + if(isActive()) { + renderer.serverTick(); + } } } diff --git a/src/main/java/makamys/lodmod/mixin/MixinChunkCache.java b/src/main/java/makamys/lodmod/mixin/MixinChunkCache.java index bbfcca1..c5b6f33 100644 --- a/src/main/java/makamys/lodmod/mixin/MixinChunkCache.java +++ b/src/main/java/makamys/lodmod/mixin/MixinChunkCache.java @@ -4,6 +4,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import makamys.lodmod.LODMod; import makamys.lodmod.renderer.FarChunkCache; import makamys.lodmod.renderer.MyRenderer; import net.minecraft.world.ChunkCache; @@ -16,8 +17,8 @@ abstract class MixinChunkCache { @Redirect(method = "<init>*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getChunkFromChunkCoords(II)Lnet/minecraft/world/chunk/Chunk;")) private Chunk redirectGetChunkFromChunkCoords(World world, int p1, int p2) { Chunk chunk = world.getChunkFromChunkCoords(p1, p2); - if(FarChunkCache.class.isInstance(this.getClass()) && chunk.isEmpty()) { - Chunk myChunk = MyRenderer.getChunkFromChunkCoords(p1, p2); + if(LODMod.isActive() && FarChunkCache.class.isInstance(this.getClass()) && chunk.isEmpty()) { + Chunk myChunk = LODMod.renderer.getChunkFromChunkCoords(p1, p2); if(myChunk != null) { chunk = myChunk; } diff --git a/src/main/java/makamys/lodmod/mixin/MixinEntityRenderer.java b/src/main/java/makamys/lodmod/mixin/MixinEntityRenderer.java index 544d131..4fe081c 100644 --- a/src/main/java/makamys/lodmod/mixin/MixinEntityRenderer.java +++ b/src/main/java/makamys/lodmod/mixin/MixinEntityRenderer.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import makamys.lodmod.LODMod; import makamys.lodmod.renderer.MyRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.EntityRenderer; @@ -22,23 +23,29 @@ abstract class MixinEntityRenderer { @Inject(method = "setupCameraTransform", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/EntityRenderer;farPlaneDistance:F", shift = At.Shift.AFTER, args = "log=true", ordinal = 0)) private void onConstructed(CallbackInfo ci) { - farPlaneDistance *= 4; + if(LODMod.isActive()) { + farPlaneDistance *= 4; + } } @Inject(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glAlphaFunc(IF)V", shift = At.Shift.AFTER, ordinal = 1)) private void afterSortAndRender(float alpha, long something, CallbackInfo ci) { - Minecraft.getMinecraft().entityRenderer.enableLightmap((double)alpha); - MyRenderer.beforeRenderTerrain(); - Minecraft.getMinecraft().entityRenderer.disableLightmap((double)alpha); + if(LODMod.isActive()) { + Minecraft.getMinecraft().entityRenderer.enableLightmap((double)alpha); + LODMod.renderer.beforeRenderTerrain(); + Minecraft.getMinecraft().entityRenderer.disableLightmap((double)alpha); + } } @Redirect(method = "setupFog", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glFogf(IF)V")) private void afterSetupFog(int pname, float param, int mode, float alpha) { - EntityLivingBase var3 = Minecraft.getMinecraft().renderViewEntity; - if(pname == GL11.GL_FOG_START && mode != 999 && mode != -1 && !var3.isPotionActive(Potion.blindness) && !Minecraft.getMinecraft().theWorld.provider.doesXZShowFog((int)var3.posX, (int)var3.posZ)) { - GL11.glFogf(pname, farPlaneDistance * 0.2f); - } else { - GL11.glFogf(pname, param); + if(LODMod.isActive()) { + EntityLivingBase var3 = Minecraft.getMinecraft().renderViewEntity; + if(pname == GL11.GL_FOG_START && mode != 999 && mode != -1 && !var3.isPotionActive(Potion.blindness) && !Minecraft.getMinecraft().theWorld.provider.doesXZShowFog((int)var3.posX, (int)var3.posZ)) { + GL11.glFogf(pname, farPlaneDistance * 0.2f); + } else { + GL11.glFogf(pname, param); + } } } } diff --git a/src/main/java/makamys/lodmod/mixin/MixinMinecraftServer.java b/src/main/java/makamys/lodmod/mixin/MixinMinecraftServer.java deleted file mode 100644 index 747cbb8..0000000 --- a/src/main/java/makamys/lodmod/mixin/MixinMinecraftServer.java +++ /dev/null @@ -1,30 +0,0 @@ -package makamys.lodmod.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import makamys.lodmod.renderer.MyRenderer; -import net.minecraft.server.MinecraftServer; - -@Mixin(MinecraftServer.class) -abstract class MixinMinecraftServer { - - @Shadow - boolean worldIsBeingDeleted; - - @Inject(method = "stopServer", at = @At("HEAD")) - public void stopServer(CallbackInfo ci) { - if(!worldIsBeingDeleted) { - MyRenderer.onStopServer(); - } - } - - @Inject(method = "updateTimeLightAndEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkSystem;networkTick()V")) - public void preServerTick(CallbackInfo ci) { - MyRenderer.serverTick(); - } - -} diff --git a/src/main/java/makamys/lodmod/mixin/MixinRenderGlobal.java b/src/main/java/makamys/lodmod/mixin/MixinRenderGlobal.java index f2b89fd..18f95a6 100644 --- a/src/main/java/makamys/lodmod/mixin/MixinRenderGlobal.java +++ b/src/main/java/makamys/lodmod/mixin/MixinRenderGlobal.java @@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import makamys.lodmod.renderer.MyRenderer; +import makamys.lodmod.LODMod; import net.minecraft.client.renderer.RenderGlobal; @Mixin(RenderGlobal.class) @@ -12,7 +12,7 @@ abstract class MixinRenderGlobal { @Redirect(method = "renderSortedRenderers", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderAllRenderLists(ID)V")) private void redirectRenderAllRenderLists(RenderGlobal thiz, int p1, double p2) { - if(MyRenderer.renderWorld) { + if(LODMod.isActive() && LODMod.renderer.renderWorld) { thiz.renderAllRenderLists(p1, p2); } } diff --git a/src/main/java/makamys/lodmod/mixin/MixinWorldRenderer.java b/src/main/java/makamys/lodmod/mixin/MixinWorldRenderer.java index abfcc4e..988b478 100644 --- a/src/main/java/makamys/lodmod/mixin/MixinWorldRenderer.java +++ b/src/main/java/makamys/lodmod/mixin/MixinWorldRenderer.java @@ -11,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import makamys.lodmod.LODMod; import makamys.lodmod.ducks.ITessellator; import makamys.lodmod.ducks.IWorldRenderer; import makamys.lodmod.renderer.ChunkMesh; @@ -55,18 +56,24 @@ abstract class MixinWorldRenderer implements IWorldRenderer { @Inject(method = "updateRenderer", at = @At(value = "HEAD")) private void preUpdateRenderer(CallbackInfo ci) { - chunkMeshes.clear(); + if(LODMod.isActive()) { + chunkMeshes.clear(); + } } @Inject(method = "updateRenderer", at = @At(value = "TAIL")) private void postUpdateRenderer(CallbackInfo ci) { - MyRenderer.onWorldRendererPost(WorldRenderer.class.cast(this)); - chunkMeshes.clear(); + if(LODMod.isActive()) { + LODMod.renderer.onWorldRendererPost(WorldRenderer.class.cast(this)); + chunkMeshes.clear(); + } } @Inject(method = "postRenderBlocks", at = @At(value = "HEAD")) private void prePostRenderBlocks(CallbackInfo ci) { - chunkMeshes.add(((ITessellator)Tessellator.instance).toChunkMesh()); + if(LODMod.isActive()) { + chunkMeshes.add(((ITessellator)Tessellator.instance).toChunkMesh()); + } } @Redirect(method = "postRenderBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;draw()I")) @@ -107,7 +114,9 @@ abstract class MixinWorldRenderer implements IWorldRenderer { @Inject(method = "setDontDraw", at = @At(value = "HEAD")) private void preSetDontDraw(CallbackInfo ci) { - MyRenderer.onDontDraw(WorldRenderer.class.cast(this)); + if(LODMod.isActive()) { + LODMod.renderer.onDontDraw(WorldRenderer.class.cast(this)); + } } @Override diff --git a/src/main/java/makamys/lodmod/renderer/LODChunk.java b/src/main/java/makamys/lodmod/renderer/LODChunk.java index bae235c..4d8dbff 100644 --- a/src/main/java/makamys/lodmod/renderer/LODChunk.java +++ b/src/main/java/makamys/lodmod/renderer/LODChunk.java @@ -2,6 +2,7 @@ package makamys.lodmod.renderer; import java.util.List; +import makamys.lodmod.LODMod; import net.minecraft.entity.Entity; import net.minecraft.world.chunk.Chunk; @@ -16,6 +17,8 @@ public class LODChunk { SimpleChunkMesh simpleMesh; ChunkMesh[] chunkMeshes = new ChunkMesh[32]; + MyRenderer renderer = LODMod.renderer; + public LODChunk(int x, int z) { this.x = x; this.z = z; @@ -33,14 +36,14 @@ public class LODChunk { public void putChunkMeshes(int cy, List<ChunkMesh> newChunkMeshes) { for(int i = 0; i < 2; i++) { if(chunkMeshes[cy * 2 + i] != null) { - MyRenderer.setMeshVisible(chunkMeshes[cy * 2 + i], false); + renderer.setMeshVisible(chunkMeshes[cy * 2 + i], false); chunkMeshes[cy * 2 + i] = null; } } for(int i = 0; i < newChunkMeshes.size(); i++) { chunkMeshes[cy * 2 + i] = newChunkMeshes.get(i); - MyRenderer.sendMeshToGPU(newChunkMeshes.get(i)); + renderer.sendMeshToGPU(newChunkMeshes.get(i)); } } @@ -56,11 +59,11 @@ public class LODChunk { public void tick(Entity player) { double distSq = distSq(player); if(distSq < Math.pow(32 * 16, 2)) { - MyRenderer.setLOD(this, 2); + renderer.setLOD(this, 2); } else if(distSq < Math.pow(64 * 16, 2)) { - MyRenderer.setLOD(this, 1); + renderer.setLOD(this, 1); } else { - MyRenderer.setVisible(this, false); + renderer.setVisible(this, false); } } diff --git a/src/main/java/makamys/lodmod/renderer/MeshQuad.java b/src/main/java/makamys/lodmod/renderer/MeshQuad.java index a48815d..dfd5f0d 100644 --- a/src/main/java/makamys/lodmod/renderer/MeshQuad.java +++ b/src/main/java/makamys/lodmod/renderer/MeshQuad.java @@ -7,6 +7,7 @@ import java.util.Locale; import java.util.Map; import makamys.lodmod.renderer.MeshQuad.QuadPlaneComparator; +import makamys.lodmod.util.SpriteUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; @@ -80,8 +81,8 @@ public class MeshQuad { TextureAtlasSprite sprite = null; Map<String, TextureAtlasSprite> uploadedSprites = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).mapUploadedSprites; - spriteIndex = MyRenderer.getSpriteIndexForUV(avgU, avgV); - sprite = MyRenderer.getSprite(spriteIndex); + spriteIndex = SpriteUtil.getSpriteIndexForUV(avgU, avgV); + sprite = SpriteUtil.getSprite(spriteIndex); if(sprite == null) { System.out.println("Error: couldn't find sprite"); diff --git a/src/main/java/makamys/lodmod/renderer/MyRenderer.java b/src/main/java/makamys/lodmod/renderer/MyRenderer.java index a1ce086..3a23a25 100644 --- a/src/main/java/makamys/lodmod/renderer/MyRenderer.java +++ b/src/main/java/makamys/lodmod/renderer/MyRenderer.java @@ -3,149 +3,148 @@ package makamys.lodmod.renderer; import net.minecraft.client.Minecraft; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.texture.ITextureObject; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ChunkCoordinates; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.gen.ChunkProviderServer; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Queue; -import java.util.Set; -import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.SynchronousQueue; -import java.util.stream.Collectors; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.BufferUtils; -import org.lwjgl.Sys; import org.lwjgl.input.Keyboard; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.ARBDebugOutputCallback; -import org.lwjgl.opengl.ARBShaderObjects; -import org.lwjgl.opengl.Display; -import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GLContext; import org.lwjgl.util.vector.Matrix4f; import makamys.lodmod.ducks.IWorldRenderer; import makamys.lodmod.util.Util; -import static org.lwjgl.opengl.ARBBufferObject.*; -import static org.lwjgl.opengl.ARBVertexBufferObject.*; import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL13.*; import static org.lwjgl.opengl.GL14.*; import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL30.*; -import static org.lwjgl.util.glu.GLU.*; public class MyRenderer { - private static boolean hasInited = false; - - private static boolean[] wasDown = new boolean[256]; - private static int renderQuads = 0; - - public static boolean renderWorld = true; - public static boolean renderLOD = true; - - //private static int[] spriteIndexMap; - public static List<TextureAtlasSprite> sprites; - - static private Map<Long, Integer> uv2spriteIndex = new HashMap<>(); - - //static ChunkMesh mesh; - - private static void destroy() { - glDeleteProgram(shaderProgram); + private boolean hasInited = false; + + private boolean[] wasDown = new boolean[256]; + private int renderQuads = 0; + + public boolean renderWorld = true; + public boolean renderLOD = true; + + private static int BUFFER_SIZE = 1024 * 1024 * 1024; + private static int MAX_MESHES = 100000; + + private int VAO, VBO, EBO, shaderProgram; + private IntBuffer piFirst, piCount; + + List<Chunk> myChunks = new ArrayList<Chunk>(); + List<LODChunk> pendingLODChunks = new ArrayList<>(); + + private boolean hasServerInited = false; + private HashMap<ChunkCoordIntPair, LODRegion> loadedRegionsMap = new HashMap<>(); + + // TODO make these packets to make this work on dedicated servers + Queue<Chunk> farChunks = new ConcurrentLinkedQueue<>(); + + List<ChunkCoordIntPair> serverChunkLoadQueue = new ArrayList<>(); + + private double lastSortX = Double.NaN; + private double lastSortY = Double.NaN; + private double lastSortZ = Double.NaN; + + public MyRenderer(){ + hasInited = init(); + } + + public void beforeRenderTerrain() { + if(hasInited) { + mainLoop(); + handleKeyboard(); + if(renderLOD) { + render(); + } + } + } + + private void mainLoop() { + while(!farChunks.isEmpty()) { + LODChunk lodChunk = receiveFarChunk(farChunks.remove()); + sendChunkToGPU(lodChunk); + } + + List<Object> players = Minecraft.getMinecraft().getIntegratedServer().getConfigurationManager().playerEntityList; + if(!players.isEmpty()) { + Entity player = (Entity)players.get(0); + + List<ChunkCoordIntPair> newServerChunkLoadQueue = new ArrayList<>(); + + if(Double.isNaN(lastSortX) || getLastSortDistanceSq(player) > 16 * 16) { + int centerX = (int)Math.floor(player.posX / 16.0); + int centerZ = (int)Math.floor(player.posZ / 16.0); + + int range = 64; + for(int x = -range; x <= range; x++) { + for(int z = -range; z <= range; z++) { + int chunkX = centerX + x; + int chunkZ = centerZ + z; + + if(getLODChunk(chunkX, chunkZ).chunk == null) { + newServerChunkLoadQueue.add(new ChunkCoordIntPair(chunkX, chunkZ)); + } + } + } + Collections.sort(newServerChunkLoadQueue, new ChunkCoordDistanceComparator(player)); + setServerChunkLoadQueue(newServerChunkLoadQueue); + + lastSortX = player.posX; + lastSortY = player.posY; + lastSortZ = player.posZ; + + loadedRegionsMap.forEach((k, v) -> v.tick(player)); + } + } + } + + public void destroy() { + /*glDeleteProgram(shaderProgram); glDeleteVertexArrays(VAO); - glDeleteBuffers(VBO); + glDeleteBuffers(VBO);*/ } - private static void mainLoop() { + private void handleKeyboard() { if(Keyboard.isKeyDown(Keyboard.KEY_F) && !wasDown[Keyboard.KEY_F]) { renderLOD = !renderLOD; } if(Keyboard.isKeyDown(Keyboard.KEY_V) && !wasDown[Keyboard.KEY_V]) { renderWorld = !renderWorld; } - if(hasInited) { - /*if(Keyboard.isKeyDown(Keyboard.KEY_X) && !wasDown[Keyboard.KEY_X]) { - renderQuads--; - if(renderQuads < 0) { - renderQuads = 0; - } - } - if(Keyboard.isKeyDown(Keyboard.KEY_C) && !wasDown[Keyboard.KEY_C]) { - renderQuads++; - if(renderQuads > mesh.quadCount) { - renderQuads = mesh.quadCount; - } - }*/ - } - for(int i = 0; i < 256; i++) { wasDown[i] = Keyboard.isKeyDown(i); } } - private static void render() { + private void render() { GL11.glPushAttrib(GL11.GL_ENABLE_BIT); - //GL11.glDisable(GL11.GL_CULL_FACE); - //GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - //GL11.glColor4f(0, 1, 0, 1); // change this for your colour - //GL11.glLineWidth(9.0F); - //GL11.glDepthMask(false); - float z = 0; - - /*GL11.glBegin(GL11.GL_TRIANGLES); - GL11.glVertex3f(-0.9f,-0.9f,0); - GL11.glVertex3f(0.9f,0.9f,0); - GL11.glVertex3f(-0.9f,0.9f,0); - GL11.glEnd();*/ - - //glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shaderProgram); @@ -166,7 +165,6 @@ public class MyRenderer { FloatBuffer projBuf = BufferUtils.createFloatBuffer(16); glGetFloat(GL_PROJECTION_MATRIX, projBuf); - //modelView.flip(); IntBuffer viewportBuf = BufferUtils.createIntBuffer(16); glGetInteger(GL_VIEWPORT, viewportBuf); @@ -192,7 +190,6 @@ public class MyRenderer { glUniformMatrix4(u_modelView, false, modelView); glUniformMatrix4(u_proj, false, projBuf); glUniformMatrix4(u_projInv, false, projInvBuf); - //glUniform4(u_viewport, viewportBuf); glUniform4f(u_viewport, viewportBuf.get(0),viewportBuf.get(1),viewportBuf.get(2),viewportBuf.get(3)); glUniform4(u_fogColor, fogColorBuf); glUniform2(u_fogStartEnd, fogStartEnd); @@ -207,15 +204,8 @@ public class MyRenderer { } glBindVertexArray(VAO); - //glEnableVertexAttribArray(0); - //glDrawArrays(GL_TRIANGLES, 0, 3); - //glActiveTexture(GL_TEXTURE1); - //ITextureObject hmm = Minecraft.getMinecraft().getTextureManager().getTexture(new ResourceLocation("dynamic/lightMap_1")); - //glBindTexture(GL_TEXTURE_2D, hmm.getGlTextureId()); - //glDrawArrays(GL_TRIANGLES, 0, 6*renderQuads); glMultiDrawArrays(GL_TRIANGLES, piFirst, piCount); - //glDisableVertexAttribArray(0); glBindVertexArray(0); glUseProgram(0); @@ -225,71 +215,13 @@ public class MyRenderer { } - private static int VAO, VBO, EBO, shaderProgram; - private static IntBuffer piFirst, piCount; - - private static String readFile(String path){ - try { - return new String(Files.readAllBytes(Util.getResourcePath(path))); - } catch (IOException e) { - e.printStackTrace(); - } - return ""; - } - - private static byte[] byteBufferToArray(ByteBuffer buffer) { - byte[] dst = new byte[buffer.remaining()]; - buffer.get(dst); - buffer.flip(); - return dst; - } - - private static int[] intBufferToArray(IntBuffer buffer) { - int[] dst = new int[buffer.remaining()]; - buffer.get(dst); - buffer.flip(); - return dst; - } - - private static int findSpriteIndexForUV(float u, float v) { - Map<String, TextureAtlasSprite> uploadedSprites = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).mapUploadedSprites; - - int spriteIndex = 0; - for(TextureAtlasSprite tas : uploadedSprites.values()) { - if(tas.getMinU() <= u && u <= tas.getMaxU() && tas.getMinV() <= v && v <= tas.getMaxV()) { - break; - } - spriteIndex++; - } - return spriteIndex; - } - - public static int getSpriteIndexForUV(float u, float v){ - long key = ChunkCoordIntPair.chunkXZ2Int((int)(u * Integer.MAX_VALUE), (int)(v * Integer.MAX_VALUE)); - int index = uv2spriteIndex.getOrDefault(key, -1); - if(index == -1) { - index = findSpriteIndexForUV(u, v); - uv2spriteIndex.put(key, index); - } - return index; - } - - public static TextureAtlasSprite getSprite(int i){ - if(i >= 0 && i < sprites.size()) { - return sprites.get(i); - } else { - return null; - } - } - - private static boolean init() { + public boolean init() { Map<String, TextureAtlasSprite> uploadedSprites = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).mapUploadedSprites; - sprites = uploadedSprites.values().stream().collect(Collectors.toList()); int vertexShader; vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, readFile("shaders/chunk.vert")); + glShaderSource(vertexShader, Util.readFile("shaders/chunk.vert")); glCompileShader(vertexShader); if(glGetShaderi(vertexShader, GL_COMPILE_STATUS) == 0) { @@ -299,7 +231,7 @@ public class MyRenderer { int fragmentShader; fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, readFile("shaders/chunk.frag")); + glShaderSource(fragmentShader, Util.readFile("shaders/chunk.frag")); glCompileShader(fragmentShader); if(glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == 0) { @@ -326,60 +258,6 @@ public class MyRenderer { EBO = glGenBuffers(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - boolean rough = false; - - /* - List<Integer> chunkCoords = new ArrayList<>();*/ - /*chunkCoords.add(-19); - chunkCoords.add(4); - chunkCoords.add(15);*/ - /*List<Mesh> meshes = new ArrayList<Mesh>(); - for(Chunk chunk : myChunks) { - Entity player = Minecraft.getMinecraft().thePlayer; - int minRadius = 0; - int radius = 10; - if(minRadius <= Math.abs(chunk.xPosition - player.chunkCoordX) && Math.abs(chunk.xPosition - player.chunkCoordX) < radius && minRadius <= Math.abs(chunk.zPosition - player.chunkCoordZ) && Math.abs(chunk.zPosition - player.chunkCoordZ) < radius) { - if(!rough) { - for(int y = 0; y < 16; y++) { - chunkCoords.add(chunk.xPosition); - chunkCoords.add(y); - chunkCoords.add(chunk.zPosition); - } - } else { - meshes.add(new SimpleChunkMesh(chunk)); - } - } - - } - long t0 = System.nanoTime(); - if(!rough) { - ChunkMesh.saveChunks(chunkCoords); - - meshes.addAll(ChunkMesh.loadAll()); - } - System.out.println("loaded " + meshes.size() + " cchunks in " + ((System.nanoTime() - t0) / 1000000000f) + "s"); - //meshes = meshes.subList(2, 3); - int bufferSize = 0; - int quadCount = 0; - Mesh firstMesh = meshes.get(0); - int stride = -1; - for(Mesh mesh : meshes) { - bufferSize += mesh.buffer.limit(); - quadCount += mesh.quadCount; - } - - if(Runtime.getRuntime().freeMemory() < BUFFER_SIZE) { - System.out.println("not enough memory"); - // TODO optimize memory usage - return false; - } - ByteBuffer buffer = BufferUtils.createByteBuffer(BUFFER_SIZE); - - for(Mesh mesh : meshes) { - int verticesSoFar = buffer.position() / firstMesh.getStride(); - buffer.put(mesh.buffer); - } - buffer.flip();*/ glBufferData(GL_ARRAY_BUFFER, BUFFER_SIZE, GL_STATIC_DRAW); @@ -395,52 +273,24 @@ public class MyRenderer { glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); - //renderQuads = quadCount; - - int nextTri = 0; piFirst = BufferUtils.createIntBuffer(MAX_MESHES); piFirst.flip(); piCount = BufferUtils.createIntBuffer(MAX_MESHES); piCount.flip(); - /*for(int i = 0; i < meshes.size(); i++) { - Mesh mesh = meshes.get(i); - - piFirst.put(nextTri); - piCount.put(mesh.quadCount * 6); - nextTri += mesh.quadCount * 6; - }*/ glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); - //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return true; } - public static boolean doRender = true; - private static boolean hasInited2 = false; - - private static int BUFFER_SIZE = 1024 * 1024 * 1024; - private static int MAX_MESHES = 100000; - - public static void beforeRenderTerrain() { - init2(); - - if(doRender) { - mainLoop(); - if(hasInited && renderLOD) { - render(); - } - } - } - - public static void onWorldRendererPost(WorldRenderer wr) { + public void onWorldRendererPost(WorldRenderer wr) { LODChunk lodChunk = getLODChunk(Math.floorDiv(wr.posX, 16), Math.floorDiv(wr.posZ, 16)); lodChunk.putChunkMeshes(Math.floorDiv(wr.posY, 16), ((IWorldRenderer)wr).getChunkMeshes()); setVisible(lodChunk, false); } - public static void onDontDraw(WorldRenderer wr) { + public void onDontDraw(WorldRenderer wr) { int chunkX = Math.floorDiv(wr.posX, 16); int chunkY = Math.floorDiv(wr.posY, 16); int chunkZ = Math.floorDiv(wr.posZ, 16); @@ -454,89 +304,29 @@ public class MyRenderer { setVisible(lodChunk, true); } - private static void init2() { - if(!hasInited2) { - hasInited = init(); - hasInited2 = true; - } else { - while(!farChunks.isEmpty()) { - LODChunk lodChunk = receiveFarChunk(farChunks.remove()); - sendChunkToGPU(lodChunk); - } - - List<Object> players = Minecraft.getMinecraft().getIntegratedServer().getConfigurationManager().playerEntityList; - if(!players.isEmpty()) { - Entity player = (Entity)players.get(0); - - List<ChunkCoordIntPair> newServerChunkLoadQueue = new ArrayList<>(); - - if(Double.isNaN(lastSortX) || getLastSortDistanceSq(player) > 16 * 16) { - int centerX = (int)Math.floor(player.posX / 16.0); - int centerZ = (int)Math.floor(player.posZ / 16.0); - - int range = 64; - for(int x = -range; x <= range; x++) { - for(int z = -range; z <= range; z++) { - int chunkX = centerX + x; - int chunkZ = centerZ + z; - - if(getLODChunk(chunkX, chunkZ).chunk == null) { - newServerChunkLoadQueue.add(new ChunkCoordIntPair(chunkX, chunkZ)); - } - } - } - Collections.sort(newServerChunkLoadQueue, new ChunkCoordDistanceComparator(player)); - setServerChunkLoadQueue(newServerChunkLoadQueue); - hasInited2 = true; - - lastSortX = player.posX; - lastSortY = player.posY; - lastSortZ = player.posZ; - - loadedRegionsMap.forEach((k, v) -> v.tick(player)); - } - } - } - } - - private static double getLastSortDistanceSq(Entity player) { + private double getLastSortDistanceSq(Entity player) { return Math.pow(lastSortX - player.posX, 2) + Math.pow(lastSortZ - player.posZ, 2); } - private static synchronized void setServerChunkLoadQueue(List<ChunkCoordIntPair> coords) { + private synchronized void setServerChunkLoadQueue(List<ChunkCoordIntPair> coords) { serverChunkLoadQueue = coords; } - private static LODChunk receiveFarChunk(Chunk chunk) { + private LODChunk receiveFarChunk(Chunk chunk) { LODRegion region = getRegionContaining(chunk.xPosition, chunk.zPosition); myChunks.add(chunk); return region.putChunk(chunk); } - private static LODChunk getLODChunk(int chunkX, int chunkZ) { + private LODChunk getLODChunk(int chunkX, int chunkZ) { return getRegionContaining(chunkX, chunkZ).getChunkAbsolute(chunkX, chunkZ); } - static List<Chunk> myChunks = new ArrayList<Chunk>(); - static List<LODChunk> pendingLODChunks = new ArrayList<>(); - - private static boolean hasServerInited = false; - private static HashMap<ChunkCoordIntPair, LODRegion> loadedRegionsMap = new HashMap<>(); - - // TODO make these packets to make this work on dedicated servers - static Queue<Chunk> farChunks = new ConcurrentLinkedQueue<>(); - - static List<ChunkCoordIntPair> serverChunkLoadQueue = new ArrayList<>(); - - private static double lastSortX = Double.NaN; - private static double lastSortY = Double.NaN; - private static double lastSortZ = Double.NaN; - - public static void onStopServer() { + public void onStopServer() { } - public static synchronized void serverTick() { + public synchronized void serverTick() { int chunkLoadsRemaining = 64; while(!serverChunkLoadQueue.isEmpty() && chunkLoadsRemaining-- > 0) { ChunkCoordIntPair coords = serverChunkLoadQueue.remove(0); @@ -546,7 +336,7 @@ public class MyRenderer { } } - private static LODRegion getRegionContaining(int chunkX, int chunkZ) { + private LODRegion getRegionContaining(int chunkX, int chunkZ) { ChunkCoordIntPair key = new ChunkCoordIntPair(Math.floorDiv(chunkX , 32), Math.floorDiv(chunkZ, 32)); LODRegion region = loadedRegionsMap.get(key); if(region == null) { @@ -556,7 +346,7 @@ public class MyRenderer { return region; } - private static void loadChunk(int chunkX, int chunkZ) { + private void loadChunk(int chunkX, int chunkZ) { LODRegion region = getRegionContaining(chunkX, chunkZ); LODChunk lodChunk = region.getChunkAbsolute(chunkX, chunkZ); if(lodChunk == null) { @@ -579,7 +369,7 @@ public class MyRenderer { sendChunkToGPU(lodChunk); } - private static void sendChunkToGPU(LODChunk lodChunk) { + private void sendChunkToGPU(LODChunk lodChunk) { lodChunk.simpleMesh = new SimpleChunkMesh(lodChunk.chunk); /*for(int cy = 0; cy < 16; cy++) { lodChunk.chunkMeshes[cy] = ChunkMesh.getChunkMesh(lodChunk.x, cy, lodChunk.z); @@ -594,21 +384,21 @@ public class MyRenderer { setVisible(lodChunk, true); } - public static void setLOD(LODChunk lodChunk, int lod) { + public void setLOD(LODChunk lodChunk, int lod) { if(lod == lodChunk.lod) return; lodChunk.lod = lod; lodChunkChanged(lodChunk); } - public static void setVisible(LODChunk lodChunk, boolean visible) { + public void setVisible(LODChunk lodChunk, boolean visible) { if(visible == lodChunk.visible) return; lodChunk.visible = visible; lodChunkChanged(lodChunk); } - public static void lodChunkChanged(LODChunk lodChunk) { + public void lodChunkChanged(LODChunk lodChunk) { int newLOD = (!lodChunk.hasChunkMeshes() && lodChunk.lod == 2) ? 1 : lodChunk.lod; if(lodChunk.simpleMesh != null) { if(lodChunk.visible && newLOD == 1) { @@ -636,11 +426,11 @@ public class MyRenderer { } } - private static int nextTri; - private static int nextMeshOffset; - private static int nextMesh; + private int nextTri; + private int nextMeshOffset; + private int nextMesh; - protected static void sendMeshToGPU(Mesh mesh) { + protected void sendMeshToGPU(Mesh mesh) { if(mesh == null) { return; } @@ -658,7 +448,7 @@ public class MyRenderer { glBindVertexArray(0); } - protected static void setMeshVisible(Mesh mesh, boolean visible) { + protected void setMeshVisible(Mesh mesh, boolean visible) { if(mesh == null) return; if(mesh.visible != visible) { @@ -693,7 +483,7 @@ public class MyRenderer { } } - public static Chunk getChunkFromChunkCoords(int x, int z) { + public Chunk getChunkFromChunkCoords(int x, int z) { for(Chunk chunk : myChunks) { if(chunk.xPosition == x && chunk.zPosition == z) { return chunk; diff --git a/src/main/java/makamys/lodmod/util/SpriteUtil.java b/src/main/java/makamys/lodmod/util/SpriteUtil.java new file mode 100644 index 0000000..34bc544 --- /dev/null +++ b/src/main/java/makamys/lodmod/util/SpriteUtil.java @@ -0,0 +1,55 @@ +package makamys.lodmod.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.world.ChunkCoordIntPair; + +public class SpriteUtil { + + private static int[] spriteIndexMap; + public static List<TextureAtlasSprite> sprites; + + private static Map<Long, Integer> uv2spriteIndex = new HashMap<>(); + + private static int findSpriteIndexForUV(float u, float v) { + Map<String, TextureAtlasSprite> uploadedSprites = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).mapUploadedSprites; + + int spriteIndex = 0; + for(TextureAtlasSprite tas : uploadedSprites.values()) { + if(tas.getMinU() <= u && u <= tas.getMaxU() && tas.getMinV() <= v && v <= tas.getMaxV()) { + break; + } + spriteIndex++; + } + return spriteIndex; + } + + public static int getSpriteIndexForUV(float u, float v){ + long key = ChunkCoordIntPair.chunkXZ2Int((int)(u * Integer.MAX_VALUE), (int)(v * Integer.MAX_VALUE)); + int index = uv2spriteIndex.getOrDefault(key, -1); + if(index == -1) { + index = findSpriteIndexForUV(u, v); + uv2spriteIndex.put(key, index); + } + return index; + } + + public static TextureAtlasSprite getSprite(int i){ + if(i >= 0 && i < sprites.size()) { + return sprites.get(i); + } else { + return null; + } + } + + public static void init() { + Map<String, TextureAtlasSprite> uploadedSprites = ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).mapUploadedSprites; + sprites = uploadedSprites.values().stream().collect(Collectors.toList()); + } +} diff --git a/src/main/java/makamys/lodmod/util/Util.java b/src/main/java/makamys/lodmod/util/Util.java index 92cc5cd..6964e9e 100644 --- a/src/main/java/makamys/lodmod/util/Util.java +++ b/src/main/java/makamys/lodmod/util/Util.java @@ -4,7 +4,10 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.nio.file.FileSystems; +import java.nio.file.Files; import java.nio.file.Path; public class Util { @@ -27,4 +30,27 @@ public class Util { return null; } } + + public static String readFile(String path){ + try { + return new String(Files.readAllBytes(Util.getResourcePath(path))); + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + + public static byte[] byteBufferToArray(ByteBuffer buffer) { + byte[] dst = new byte[buffer.remaining()]; + buffer.get(dst); + buffer.flip(); + return dst; + } + + public static int[] intBufferToArray(IntBuffer buffer) { + int[] dst = new int[buffer.remaining()]; + buffer.get(dst); + buffer.flip(); + return dst; + } } diff --git a/src/main/resources/lodmod.mixin.json b/src/main/resources/lodmod.mixin.json index d8bfed1..65e6dd4 100644 --- a/src/main/resources/lodmod.mixin.json +++ b/src/main/resources/lodmod.mixin.json @@ -7,7 +7,6 @@ "mixins": [ "MixinChunkCache", "MixinEntityRenderer", - "MixinMinecraftServer", "MixinRenderGlobal", "MixinSoundManager", "MixinSoundManager", |