Close #18 (allow client use on servers)

This commit is contained in:
James Seibel
2021-04-03 12:05:16 -05:00
parent e1216966a3
commit 9e5aac3bf7
7 changed files with 165 additions and 49 deletions
@@ -15,6 +15,7 @@ import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.color.BlockColors;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IWorld;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
@@ -55,13 +56,13 @@ public class LodBuilder
public void generateLodChunkAsync(IChunk chunk, LodWorld lodWorld, DimensionType dim)
public void generateLodChunkAsync(IChunk chunk, LodWorld lodWorld, IWorld world)
{
if (lodWorld == null || !lodWorld.getIsWorldLoaded())
return;
// is this chunk from the same world as the lodWorld?
if (!lodWorld.getWorldName().equals(LodUtils.getCurrentWorldID()))
if (!lodWorld.getWorldName().equals(LodUtils.getWorldID(world)))
// we are not in the same world anymore
// don't add this LOD
return;
@@ -77,13 +78,15 @@ public class LodBuilder
{
try
{
DimensionType dim = world.getDimensionType();
LodChunk lod = generateLodFromChunk(chunk);
LodDimension lodDim;
if (lodWorld.getLodDimension(dim) == null)
{
lodDim = new LodDimension(dim, regionWidth);
lodDim = new LodDimension(dim, lodWorld, regionWidth);
lodWorld.addLodDimension(lodDim);
}
else
@@ -62,7 +62,7 @@ public class LodChunkGenWorker implements IWorker
//System.out.println(endTime - startTime + "\t" + lodBuilder.hasBlockData(chunk));
lodBuilder.generateLodChunkAsync(chunk, ClientProxy.getLodWorld(), serverWorld.getDimensionType());
lodBuilder.generateLodChunkAsync(chunk, ClientProxy.getLodWorld(), serverWorld);
// this is called so that the new LOD chunk is drawn
// after it is generated
lodRenderer.regenerateLODsNextFrame();
@@ -12,8 +12,6 @@ import com.backsun.lod.objects.LodChunk;
import com.backsun.lod.objects.LodDimension;
import com.backsun.lod.objects.LodRegion;
import net.minecraft.client.Minecraft;
/**
* This object handles creating LodRegions
* from files and saving LodRegion objects
@@ -63,11 +61,6 @@ public class LodDimensionFileHandler
*/
public LodRegion loadRegionFromFile(int regionX, int regionZ)
{
// we don't currently support reading or writing
// files when connected to a server
if (!Minecraft.getInstance().isIntegratedServerRunning())
return null;
if (!readyToReadAndWrite())
return null;
@@ -138,11 +131,6 @@ public class LodDimensionFileHandler
*/
public synchronized void saveDirtyRegionsToFileAsync()
{
// we don't currently support reading or writing
// files when connected to a server
if (!Minecraft.getInstance().isIntegratedServerRunning())
return;
if (!readyToReadAndWrite())
// we aren't ready to read and write yet
return;
@@ -231,7 +219,7 @@ public class LodDimensionFileHandler
// ".\Super Flat\DIM-1\data"
// or
// ".\Super Flat\data"
return dimensionDataSaveFolder.getCanonicalPath() + "\\lod\\" +
return dimensionDataSaveFolder.getCanonicalPath() + "\\" +
FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION;
}
catch(IOException e)
@@ -1,11 +1,16 @@
package com.backsun.lod.objects;
import java.io.File;
import java.io.IOException;
import com.backsun.lod.handlers.LodDimensionFileHandler;
import com.backsun.lod.util.LodUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.DimensionType;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
/**
* This object holds all loaded LOD regions
@@ -30,13 +35,42 @@ public class LodDimension
private LodDimensionFileHandler fileHandler;
public LodDimension(DimensionType newDimension, int newMaxWidth)
public LodDimension(DimensionType newDimension, LodWorld lodWorld, int newMaxWidth)
{
dimension = newDimension;
width = newMaxWidth;
ServerChunkProvider provider = LodUtils.getServerWorldFromDimension(newDimension).getChunkProvider();
fileHandler = new LodDimensionFileHandler(provider.getSavedData().folder, this);
try
{
Minecraft mc = Minecraft.getInstance();
File saveDir;
if(mc.isIntegratedServerRunning())
{
// local world
ServerWorld serverWorld = LodUtils.getServerWorldFromDimension(newDimension);
// provider needs a separate variable to prevent
// the compiler from complaining
ServerChunkProvider provider = serverWorld.getChunkProvider();
saveDir = new File(provider.getSavedData().folder.getCanonicalFile() + "\\lod");
}
else
{
// connected to server
saveDir = new File(mc.gameDir.getCanonicalFile() +
"\\lod server data\\" + LodUtils.getDimensionIDFromWorld(mc.world));
}
fileHandler = new LodDimensionFileHandler(saveDir, this);
}
catch(IOException e)
{
// the file handler wasn't able to be created
// we won't be able to read or write any files
}
regions = new LodRegion[width][width];
isRegionDirty = new boolean[width][width];
@@ -229,7 +263,7 @@ public class LodDimension
region.addLod(lod);
// don't save empty place holders to disk
if (!lod.isPlaceholder())
if (!lod.isPlaceholder() && fileHandler != null)
{
// mark the region as dirty so it will be saved to disk
int xIndex = (pos.x - centerX) + halfWidth;
@@ -265,7 +299,10 @@ public class LodDimension
*/
public LodRegion getRegionFromFile(int regionX, int regionZ)
{
return fileHandler.loadRegionFromFile(regionX, regionZ);
if (fileHandler != null)
return fileHandler.loadRegionFromFile(regionX, regionZ);
else
return null;
}
@@ -19,9 +19,11 @@ public class LodWorld
/** If true then the LOD world is setup and ready to use */
private boolean isWorldLoaded = false;
public static final String NO_WORLD_LOADED = "No world loaded";
public LodWorld()
{
worldName = "No world loaded";
worldName = NO_WORLD_LOADED;
}
/**
@@ -31,6 +33,17 @@ public class LodWorld
*/
public void selectWorld(String newWorldName)
{
if(newWorldName.isEmpty())
{
deselectWorld();
return;
}
if (worldName.equals(newWorldName))
// don't recreate everything if we
// didn't actually change worlds
return;
worldName = newWorldName;
lodDimensions = new Hashtable<DimensionType, LodDimension>();
isWorldLoaded = true;
@@ -43,7 +56,7 @@ public class LodWorld
*/
public void deselectWorld()
{
worldName = "No world loaded";
worldName = NO_WORLD_LOADED;
lodDimensions = null;
isWorldLoaded = false;
}
@@ -14,9 +14,6 @@ import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
//TODO Find a way to replace getIntegratedServer so this mod could be used on non-local worlds.
// Minecraft.getMinecraft().getIntegratedServer()
/**
* This handles all events sent to the client,
* and is the starting point for most of this program.
@@ -51,9 +48,12 @@ public class ClientProxy
*/
public void renderLods(float partialTicks)
{
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
return;
// update each regions' width to match the new render distance
int newWidth = Math.max(4, (mc.gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE);
if (lodWorld != null && lodBuilder.regionWidth != newWidth)
if (lodBuilder.regionWidth != newWidth)
{
lodWorld.resizeDimensionRegionWidth(newWidth);
lodBuilder.regionWidth = newWidth;
@@ -63,10 +63,6 @@ public class ClientProxy
return;
}
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
return;
LodDimension lodDim = lodWorld.getLodDimension(mc.player.world.getDimensionType());
if (lodDim == null)
return;
@@ -99,27 +95,33 @@ public class ClientProxy
@SubscribeEvent
public void chunkLoadEvent(ChunkEvent.Load event)
{
lodBuilder.generateLodChunkAsync(event.getChunk(), lodWorld, event.getWorld().getDimensionType());
lodBuilder.generateLodChunkAsync(event.getChunk(), lodWorld, event.getWorld());
}
@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event)
{
// update the LodWorld to use the new world the player
// is loaded
lodWorld.selectWorld(LodUtils.getCurrentWorldID());
// the player just loaded a new world/dimension
lodWorld.selectWorld(LodUtils.getWorldID(event.getWorld()));
// make sure the correct LODs are being rendered
// (if this isn't done the previous world's LODs may be drawn)
renderer.regenerateLODsNextFrame();
}
@SubscribeEvent
public void worldUnloadEvent(WorldEvent.Unload event)
{
lodWorld.deselectWorld();
// the player just loaded a new world/dimension
if(mc.getConnection().getWorld() == null)
// the player has disconnected from a server
lodWorld.deselectWorld();
}
@SubscribeEvent
public void worldChangeEvent(BlockEvent event)
public void blockChangeEvent(BlockEvent event)
{
if (event.getClass() == BlockEvent.BreakEvent.class ||
event.getClass() == BlockEvent.EntityPlaceEvent.class ||
@@ -128,7 +130,7 @@ public class ClientProxy
event.getClass() == BlockEvent.PortalSpawnEvent.class)
{
// recreate the LOD where the blocks were changed
lodBuilder.generateLodChunkAsync(event.getWorld().getChunk(event.getPos()), lodWorld, event.getWorld().getDimensionType());
lodBuilder.generateLodChunkAsync(event.getWorld().getChunk(event.getPos()), lodWorld, event.getWorld());
}
}
@@ -8,6 +8,7 @@ import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IWorld;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.server.ServerChunkProvider;
@@ -109,32 +110,104 @@ public class LodUtils
return false;
}
public static String getCurrentDimensionID()
{
Minecraft mc = Minecraft.getInstance();
if(mc.isIntegratedServerRunning())
{
// this will return the world save location
// and the dimension folder
if(mc.world == null)
return "";
ServerWorld serverWorld = LodUtils.getServerWorldFromDimension(mc.world.getDimensionType());
if(serverWorld == null)
return "";
ServerChunkProvider provider = serverWorld.getChunkProvider();
if(provider == null)
return "";
return provider.getSavedData().folder.toString();
}
else
{
ServerData server = mc.getCurrentServerData();
return server.serverName + ", IP " +
server.serverIP + ", GameVersion " +
server.gameVersion.getString() + "\\"
+ "dim_" + mc.world.getDimensionType().getEffects().getPath() + "\\";
}
}
/**
* If on single player this will return the name of the user's
* world, if in multiplayer it will return the server name
* and game version.
* world and the dimensional save folder, if in multiplayer
* it will return the server name, game version, and dimension.<br>
* <br>
* This can be used to determine where to save files for a given
* dimension.
*/
public static String getCurrentWorldID()
public static String getDimensionIDFromWorld(IWorld world)
{
Minecraft mc = Minecraft.getInstance();
if(mc.isIntegratedServerRunning())
{
ServerWorld serverWorld = LodUtils.getFirstValidServerWorld();
if (serverWorld == null)
throw new NullPointerException("getCurrentWorldID tried to get the ServerWorld but it was null");
// this will return the world save location
// and the dimension folder
ServerWorld serverWorld = LodUtils.getServerWorldFromDimension(world.getDimensionType());
if(serverWorld == null)
throw new NullPointerException("getDimensionIDFromWorld wasn't able to get the ServerWorld for the dimension " + world.getDimensionType().getEffects().getPath());
ServerChunkProvider provider = serverWorld.getChunkProvider();
if(provider != null)
return provider.getSavedData().folder.toString();
if(provider == null)
throw new NullPointerException("getDimensionIDFromWorld wasn't able to get the ServerChunkProvider for the dimension " + world.getDimensionType().getEffects().getPath());
return "";
return provider.getSavedData().folder.toString();
}
else
{
ServerData server = mc.getCurrentServerData();
return server.serverName + ", IP " + server.serverIP + ", GameVersion " + server.gameVersion.getString();
return server.serverName + ", IP " +
server.serverIP + ", GameVersion " +
server.gameVersion.getString() + "\\"
+ "dim_" + world.getDimensionType().getEffects().getPath() + "\\";
}
}
/**
* If on single player this will return the name of the user's
* world, if in multiplayer it will return the server name
* and game version.
*/
public static String getWorldID(IWorld world)
{
if(mc.isIntegratedServerRunning())
{
// chop off the dimension ID as it is not needed/wanted
String dimId = getDimensionIDFromWorld(world);
// get the world name
int saveIndex = dimId.indexOf("saves") + 1 + "saves".length();
int slashIndex = dimId.indexOf('\\', saveIndex);
dimId = dimId.substring(saveIndex, slashIndex);
return dimId;
}
else
{
ServerData server = mc.getCurrentServerData();
return server.serverName + ", IP " +
server.serverIP + ", GameVersion " +
server.gameVersion.getString();
}
}