Merge remote-tracking branch 'origin/main'

This commit is contained in:
coolGi
2022-07-18 15:16:30 +09:30
73 changed files with 1295 additions and 379 deletions
@@ -2,7 +2,6 @@ package com.seibel.lod.core;
import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.jar.DarkModeDetector;
import com.seibel.lod.core.jar.gui.BaseJFrame;
import com.seibel.lod.core.jar.gui.cusomJObject.JBox;
@@ -1,27 +1,15 @@
package com.seibel.lod.core.a7.datatype;
import java.util.ConcurrentModificationException;
import java.util.concurrent.*;
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
import com.seibel.lod.core.a7.datatype.transform.LodDataBuilder;
import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.ELodDirection;
import com.seibel.lod.core.enums.config.EBlocksToAvoid;
import com.seibel.lod.core.enums.config.EDistanceGenerationMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.objects.DHBlockPos;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.objects.lod.LodRegion;
import com.seibel.lod.core.util.*;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.LogManager;
public class LodBuilder {
@@ -22,14 +22,14 @@ package com.seibel.lod.core.a7.datatype.column.render;
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodQuadBuilder;
import com.seibel.lod.core.enums.ELodDirection;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.util.DataPointUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
public class ColumnBox
{
private static final IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public static void addBoxQuadsToBuilder(LodQuadBuilder builder, short xSize, short ySize, short zSize, short x,
short y, short z, int color, byte skyLight, byte blockLight, long topData, long botData, ColumnArrayView[][] adjData)
@@ -1,6 +1,6 @@
package com.seibel.lod.core.a7.datatype.full;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
@@ -12,7 +12,7 @@ import java.util.Objects;
// WARNING: This is not THREAD-SAFE!
public class IdBiomeBlockStateMap {
public static final IWrapperFactory FACTORY = SingletonHandler.INSTANCE.get(IWrapperFactory.class);
public static final IWrapperFactory FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
public static final class Entry {
public final IBiomeWrapper biome;
@@ -8,7 +8,7 @@ import com.seibel.lod.core.a7.pos.DhBlockPos2D;
import com.seibel.lod.core.a7.render.RenderBufferHandler;
import com.seibel.lod.core.a7.save.structure.ClientOnlySaveStructure;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.render.a7LodRenderer;
@@ -23,7 +23,7 @@ import java.util.concurrent.CompletableFuture;
public class DhClientLevel implements IClientLevel {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public final ClientOnlySaveStructure save;
public final RemoteDataFileHandler dataFileHandler;
public final RenderFileHandler renderFileHandler;
@@ -8,7 +8,7 @@ import com.seibel.lod.core.a7.pos.DhBlockPos2D;
import com.seibel.lod.core.a7.render.RenderBufferHandler;
import com.seibel.lod.core.a7.save.structure.LocalSaveStructure;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.render.a7LodRenderer;
@@ -23,7 +23,7 @@ import java.util.concurrent.CompletableFuture;
public class DhClientServerLevel implements IClientLevel, IServerLevel {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public final LocalSaveStructure save;
public final LocalDataFileHandler dataFileHandler;
public RenderFileHandler renderFileHandler = null;
@@ -1,7 +1,7 @@
package com.seibel.lod.core.a7.save.io;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.handlers.dimensionFinder.PlayerData;
import com.seibel.lod.core.handlers.dimensionFinder.SubDimCompare;
import com.seibel.lod.core.logging.ConfigBasedLogger;
@@ -20,7 +20,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
public class LevelToFileMatcher implements AutoCloseable {
private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(),
() -> Config.Client.Advanced.Debugging.DebugSwitch.logFileSubDimEvent.get());
@@ -3,7 +3,7 @@ package com.seibel.lod.core.a7.save.structure;
import com.seibel.lod.core.a7.save.io.LevelToFileMatcher;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.config.EServerFolderNameMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.ParsedIp;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -18,7 +18,7 @@ import java.util.stream.Stream;
public class ClientOnlySaveStructure extends SaveStructure {
final File folder;
private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\/:*?\"<>|]";
private static String getServerFolderName()
{
@@ -1,15 +1,13 @@
package com.seibel.lod.core.a7.save.structure;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import java.io.File;
public class LocalSaveStructure extends SaveStructure {
private static final IMinecraftSharedWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftSharedWrapper.class);
private static final IMinecraftSharedWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class);
private File debugPath = new File("");
@@ -1,16 +0,0 @@
package com.seibel.lod.core.api.external.items.interfaces.events;
import com.seibel.lod.core.api.external.items.objects.events.DhApiAfterRenderEvent;
/**
* @author James Seibel
* @version 2022-7-13
*/
public interface IDhApiAfterRenderEventHandler extends IDhApiEventHandler<DhApiAfterRenderEvent>
{
/**
* Called after Distant Horizons' rendering pipeline finishes.
*/
void afterRender(DhApiAfterRenderEvent event);
}
@@ -1,20 +0,0 @@
package com.seibel.lod.core.api.external.items.interfaces.events;
import com.seibel.lod.core.api.external.items.objects.events.DhApiRenderEvent;
/**
* @author James Seibel
* @version 2022-7-14
*/
public interface IDhApiBeforeRenderEventHandler extends IDhApiEventHandler<DhApiRenderEvent>
{
/**
* Called before Distant Horizons starts rendering. <Br>
* If this method returns false; DH's rendering will be skipped for that frame. <Br> <Br>
*
* The Matrices received are not passed on to the renderer and can be safely
* edited without modifying Minecraft or Distant Horizons' rendering.
*/
boolean beforeRender(DhApiRenderEvent event);
}
@@ -1,15 +0,0 @@
package com.seibel.lod.core.api.external.items.interfaces.events;
/**
* All Api event handlers should implement this.
*
* @param <InputType> This is the datatype that should be passed into the
* event handler's method.
*
* @author James Seibel
* @version 2022-7-13
*/
public interface IDhApiEventHandler<InputType>
{
}
@@ -1,11 +0,0 @@
package com.seibel.lod.core.api.external.items.objects.events;
/**
* @author James Seibel
* @version 2022-7-14
*/
public class DhApiAfterRenderEvent extends DhApiRenderEvent
{
/** False if DH rendering was disabled or canceled for this frame. */
public boolean renderingEnabled;
}
@@ -1,23 +0,0 @@
package com.seibel.lod.core.api.external.items.objects.events;
import com.seibel.lod.core.api.external.items.interfaces.world.IDhApiLevelWrapper;
import com.seibel.lod.core.api.external.items.objects.math.DhApiMat4f;
/**
* @author James Seibel
* @version 2022-7-14
*/
public class DhApiRenderEvent
{
public IDhApiLevelWrapper levelWrapper;
// the matrices received from Minecraft
public DhApiMat4f mcModelViewMatrix;
public DhApiMat4f mcProjectionMatrix;
// the matrices used by Distant Horizons
public DhApiMat4f dhModelViewMatrix;
public DhApiMat4f dhProjectionMatrix;
public float partialTicks;
}
@@ -1,35 +1,51 @@
package com.seibel.lod.core.api.external.methods.events;
import com.seibel.lod.core.api.external.items.interfaces.events.IDhApiEventHandler;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
import com.seibel.lod.core.api.external.items.objects.DhApiResult;
import com.seibel.lod.core.handlers.dependencyInjection.DhApiEventInjector;
/**
* Handles adding/removing event handlers.
*
* @author James Seibel
* @version 2022-7-14
* @version 2022-7-16
*/
public class DhApiEventRegister
{
/**
* Registers the given event handler. <Br>
* Only one eventHandler of a specific class can be added at a time.
* Only one eventHandler of a specific class can be registered at a time.
* If multiple of the same eventHandler are added DhApiResult will return
* the name of the already added handler and success = false.
*/
public static DhApiResult on(IDhApiEventHandler<?> eventHandler)
public static DhApiResult on(Class<? extends IDhApiEvent> eventInterface, IDhApiEvent eventHandlerImplementation)
{
throw new UnsupportedOperationException();
try
{
DhApiEventInjector.INSTANCE.bind(eventInterface, eventHandlerImplementation);
return new DhApiResult(true, "");
}
catch (IllegalStateException e)
{
return new DhApiResult(false, e.getMessage());
}
}
/**
* Removes the given event handler for this event if one has been registered. <br>
* Unregisters the given event handler for this event if one has been registered. <br>
* If no eventHandler of the given class has been registered the result will return
* success = false.
*/
public static DhApiResult off(IDhApiEventHandler<?> eventHandler)
public static DhApiResult off(Class<? extends IDhApiEvent> eventInterface, Class<IDhApiEvent> eventHandlerClass)
{
throw new UnsupportedOperationException();
if (DhApiEventInjector.INSTANCE.unbind(eventInterface, eventHandlerClass))
{
return new DhApiResult(true, "");
}
else
{
return new DhApiResult(false, "No event handler [" + eventHandlerClass.getSimpleName() + "] was bound for the event [" + eventInterface.getSimpleName() + "].");
}
}
}
@@ -0,0 +1,28 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiAfterDhInitEvent implements IDhApiEvent<Void>
{
/** Fired after Distant Horizons finishes its initial setup on Minecraft startup. */
public abstract void afterDistantHorizonsInit();
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(Void ignoredParam)
{
afterDistantHorizonsInit();
return false;
}
@Override
public final boolean getCancelable() { return false; }
}
@@ -0,0 +1,49 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.external.items.objects.math.DhApiMat4f;
import com.seibel.lod.core.api.external.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiAfterRenderEvent implements IDhApiEvent<DhApiAfterRenderEvent.EventParam>
{
/** Fired after Distant Horizons finishes rendering fake chunks. */
public abstract void afterRender(EventParam input);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(EventParam input)
{
afterRender(input);
return false;
}
@Override
public final boolean getCancelable() { return false; }
//==================//
// parameter object //
//==================//
public static class EventParam extends DhApiRenderParam
{
public EventParam(
DhApiMat4f newMinecraftProjectionMatrix, DhApiMat4f newMinecraftModelViewMatrix,
DhApiMat4f newDistantHorizonsProjectionMatrix, DhApiMat4f newDistantHorizonsModelViewMatrix,
float newPartialTicks)
{
super(newMinecraftProjectionMatrix, newMinecraftModelViewMatrix,
newDistantHorizonsProjectionMatrix, newDistantHorizonsModelViewMatrix,
newPartialTicks);
}
}
}
@@ -0,0 +1,28 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiBeforeDhInitEvent implements IDhApiEvent<Void>
{
/** Fired before Distant Horizons starts its initial setup on Minecraft startup. */
public abstract void beforeDistantHorizonsInit();
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(Void ignoredParam)
{
beforeDistantHorizonsInit();
return false;
}
@Override
public final boolean getCancelable() { return false; }
}
@@ -0,0 +1,52 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.external.items.objects.math.DhApiMat4f;
import com.seibel.lod.core.api.external.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiBeforeRenderEvent implements IDhApiEvent<DhApiBeforeRenderEvent.EventParam>
{
/**
* Fired before Distant Horizons finishes rendering fake chunks.
*
* @return whether the event should be canceled or not.
*/
public abstract boolean beforeRender(EventParam input);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(EventParam input)
{
return beforeRender(input);
}
@Override
public final boolean getCancelable() { return true; }
//==================//
// parameter object //
//==================//
public static class EventParam extends DhApiRenderParam
{
public EventParam(
DhApiMat4f newMinecraftProjectionMatrix, DhApiMat4f newMinecraftModelViewMatrix,
DhApiMat4f newDistantHorizonsProjectionMatrix, DhApiMat4f newDistantHorizonsModelViewMatrix,
float newPartialTicks)
{
super(newMinecraftProjectionMatrix, newMinecraftModelViewMatrix,
newDistantHorizonsProjectionMatrix, newDistantHorizonsModelViewMatrix,
newPartialTicks);
}
}
}
@@ -0,0 +1,30 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.external.items.interfaces.world.IDhApiLevelWrapper;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiClientSaveEvent implements IDhApiEvent<Void>
{
/** Fired after Distant Horizons saves LOD data for the client. */
public abstract void save();
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(Void ignoredParam)
{
save();
return false;
}
@Override
public final boolean getCancelable() { return false; }
}
@@ -0,0 +1,47 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.external.items.interfaces.world.IDhApiLevelWrapper;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiLevelLoadEvent implements IDhApiEvent<DhApiLevelLoadEvent.EventParam>
{
/** Fired after Distant Horizons loads a new level. */
public abstract void levelLoad(EventParam input);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(EventParam input)
{
levelLoad(input);
return false;
}
@Override
public final boolean getCancelable() { return false; }
//==================//
// parameter object //
//==================//
public static class EventParam
{
/** The newly loaded level. */
public final IDhApiLevelWrapper levelWrapper;
public EventParam(IDhApiLevelWrapper newLevelWrapper)
{
this.levelWrapper = newLevelWrapper;
}
}
}
@@ -0,0 +1,47 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.external.items.interfaces.world.IDhApiLevelWrapper;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiLevelUnloadEvent implements IDhApiEvent<DhApiLevelUnloadEvent.EventParam>
{
/** Fired after Distant Horizons unloads a level. */
public abstract void levelUnload(EventParam input);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(EventParam input)
{
levelUnload(input);
return false;
}
@Override
public final boolean getCancelable() { return false; }
//==================//
// parameter object //
//==================//
public static class EventParam
{
/** The recently unloaded level. */
public final IDhApiLevelWrapper levelWrapper;
public EventParam(IDhApiLevelWrapper newLevelWrapper)
{
this.levelWrapper = newLevelWrapper;
}
}
}
@@ -0,0 +1,29 @@
package com.seibel.lod.core.api.external.methods.events.abstractEvents;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* @author James Seibel
* @version 2022-7-17
*/
public abstract class DhApiServerSaveEvent implements IDhApiEvent<Void>
{
/** Fired after Distant Horizons saves LOD data for the server. */
public abstract void save();
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(Void ignoredParam)
{
save();
return false;
}
@Override
public final boolean getCancelable() { return false; }
}
@@ -0,0 +1,41 @@
package com.seibel.lod.core.api.external.methods.events.sharedParameterObjects;
import com.seibel.lod.core.api.external.items.objects.math.DhApiMat4f;
/**
* Parameter passed into Render events.
*
* @author James Seibel
* @version 7-17-2022
*/
public class DhApiRenderParam
{
/** The projection matrix Minecraft is using to render this frame. */
public final DhApiMat4f MinecraftProjectionMatrix;
/** The model view matrix Minecraft is using to render this frame. */
public final DhApiMat4f MinecraftModelViewMatrix;
/** The projection matrix Distant Horizons is using to render this frame. */
public final DhApiMat4f DistantHorizonsProjectionMatrix;
/** The model view matrix Distant Horizons is using to render this frame. */
public final DhApiMat4f DistantHorizonsModelViewMatrix;
/** Indicates how far into this tick the frame is. */
public final float partialTicks;
protected DhApiRenderParam(
DhApiMat4f newMinecraftProjectionMatrix, DhApiMat4f newMinecraftModelViewMatrix,
DhApiMat4f newDistantHorizonsProjectionMatrix, DhApiMat4f newDistantHorizonsModelViewMatrix,
float newPartialTicks)
{
this.MinecraftProjectionMatrix = newMinecraftProjectionMatrix;
this.MinecraftModelViewMatrix = newMinecraftModelViewMatrix;
this.DistantHorizonsProjectionMatrix = newDistantHorizonsProjectionMatrix;
this.DistantHorizonsModelViewMatrix = newDistantHorizonsModelViewMatrix;
this.partialTicks = newPartialTicks;
}
}
@@ -1,4 +1,4 @@
package com.seibel.lod.core.api.implementation.interfaces;
package com.seibel.lod.core.api.implementation.interfaces.config;
/**
@@ -7,7 +7,7 @@ package com.seibel.lod.core.api.implementation.interfaces;
* @param <CoreType> The type used by DH Core (not visible to the API user)
* @param <ApiType> The type used by DH API (not used by Core)
* @author James Seibel
* @version 2022-6-30
* @version 2022-7-16
*/
public interface IConverter<CoreType, ApiType>
{
@@ -0,0 +1,21 @@
package com.seibel.lod.core.api.implementation.interfaces.events;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
/**
* A combination of all interfaces required by
* DH Api events.
*
* @param <InputType> This is the datatype that should be passed into the
* event handler's method.
*
* @author James Seibel
* @version 2022-7-16
*/
public interface IDhApiEvent<InputType> extends IDhApiEventExternal<InputType>, IDhApiEventInternal<InputType>, IBindable
{
// Don't add any methods here.
// Add them to: IDhApiEventExternal or IDhApiEventInternal
// (depending on if they should be available to
// implementing developers or only DH devs)
}
@@ -0,0 +1,26 @@
package com.seibel.lod.core.api.implementation.interfaces.events;
/**
* Contains any methods that can be implemented by
* mod developers that wish to register events with the DH Api. <br> <br>
*
* All Api events should implement this.
*
* @param <InputType> This is the datatype that should be passed into the
* event handler's method.
*
* @author James Seibel
* @version 2022-7-16
*/
public interface IDhApiEventExternal<InputType> extends IDhApiEventInternal<InputType>
{
/**
* Returns if the event should be automatically unbound
* after firing. <br>
* Can be useful for one time setup events or waiting for a specific game state. <br> <Br>
*
* Defaults to False (the event will not be removed after firing).
*/
default boolean removeAfterFiring() { return false; };
}
@@ -0,0 +1,33 @@
package com.seibel.lod.core.api.implementation.interfaces.events;
/**
* Contains methods that should only be used internally
* by Distant Horizons and should all be locked with
* the "final" keyword. <br>
* (IE: whether an event is cancelable or not should only be defined by the DH API) <br> <br>
*
* All Api events should implement this.
*
* @param <InputType> This is the datatype that should be passed into the
* event handler's method.
*
* @author James Seibel
* @version 2022-7-16
*/
public interface IDhApiEventInternal<InputType>
{
/** Returns true if the event can be canceled. */
boolean getCancelable();
/**
* Called internally by Distant Horizons when the event happens.
* This method shouldn't directly be overridden and instead
* should point to the more specific event method.
*
* @param input the parameter object passed in from the event source. Can be null.
* @return whether the event should be canceled or not.
* A canceled event will still fire the other event handlers that are queued.
*/
boolean onEvent(InputType input);
}
@@ -1,6 +1,6 @@
package com.seibel.lod.core.api.implementation.objects;
import com.seibel.lod.core.api.implementation.interfaces.IConverter;
import com.seibel.lod.core.api.implementation.interfaces.config.IConverter;
/**
@@ -1,6 +1,6 @@
package com.seibel.lod.core.api.implementation.objects;
import com.seibel.lod.core.api.implementation.interfaces.IConverter;
import com.seibel.lod.core.api.implementation.interfaces.config.IConverter;
/**
* This assumes the two enums contain the same values.
@@ -1,6 +1,6 @@
package com.seibel.lod.core.api.implementation.objects;
import com.seibel.lod.core.api.implementation.interfaces.IConverter;
import com.seibel.lod.core.api.implementation.interfaces.config.IConverter;
import com.seibel.lod.core.enums.rendering.ERendererMode;
/**
@@ -1,7 +1,7 @@
package com.seibel.lod.core.api.implementation.wrappers;
import com.seibel.lod.core.api.external.items.interfaces.config.IDhApiConfig;
import com.seibel.lod.core.api.implementation.interfaces.IConverter;
import com.seibel.lod.core.api.implementation.interfaces.config.IConverter;
import com.seibel.lod.core.api.implementation.objects.DefaultConverter;
import com.seibel.lod.core.config.types.ConfigEntry;
@@ -25,7 +25,7 @@ import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.enums.rendering.EDebugMode;
import com.seibel.lod.core.enums.rendering.ERendererMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
import com.seibel.lod.core.logging.SpamReducedLogger;
@@ -60,8 +60,8 @@ public class ClientApi
public static final ClientApi INSTANCE = new ClientApi();
public static RenderSystemTest testRenderer = new RenderSystemTest();
private static final IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
public static final boolean ENABLE_LAG_SPIKE_LOGGING = false;
public static final long LAG_SPIKE_THRESHOLD_NS = TimeUnit.NANOSECONDS.convert(16, TimeUnit.MILLISECONDS);
@@ -22,7 +22,7 @@ package com.seibel.lod.core.api.internal.a7;
import com.seibel.lod.core.a7.world.DhClientServerWorld;
import com.seibel.lod.core.a7.world.DhServerWorld;
import com.seibel.lod.core.a7.world.IServerWorld;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
@@ -43,7 +43,7 @@ public class ServerApi
public static final boolean ENABLE_STACK_DUMP_LOGGING = false;
public static final ServerApi INSTANCE = new ServerApi();
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
private static final IVersionConstants VERSION_CONSTANTS = SingletonHandler.INSTANCE.get(IVersionConstants.class);
private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class);
private ServerApi()
{
@@ -20,7 +20,7 @@
package com.seibel.lod.core.builders.lodBuilding.bufferBuilding;
import com.seibel.lod.core.enums.rendering.EDebugMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.LodDataView;
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
import com.seibel.lod.core.a7.datatype.column.render.ColumnBox;
@@ -38,7 +38,7 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
*/
public class CubicLodTemplate
{
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.INSTANCE.get(ILodConfigWrapperSingleton.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonInjector.INSTANCE.get(ILodConfigWrapperSingleton.class);
public static void addLodToBuffer(long data, long topData, long botData, LodDataView[][] adjData,
boolean[] adjFillBlack, byte detailLevel, int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, EDebugMode debugging)
@@ -19,19 +19,17 @@
package com.seibel.lod.core.builders.worldGeneration;
import com.seibel.lod.core.a7.level.IClientLevel;
import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.config.EDistanceGenerationMode;
import com.seibel.lod.core.enums.config.EGenerationPriority;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.objects.PosToGenerateContainer;
import com.seibel.lod.core.util.LevelPosUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
import org.apache.logging.log4j.Logger;
@@ -42,8 +40,8 @@ public class BatchGenerator
{
public static final boolean ENABLE_GENERATOR_STATS_LOGGING = false;
private static final IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IWrapperFactory FACTORY = SingletonHandler.INSTANCE.get(IWrapperFactory.class);
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IWrapperFactory FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
public AbstractBatchGenerationEnvionmentWrapper generationGroup;
public ILevel targetLodLevel;
public static final int generationGroupSize = 4;
@@ -6,7 +6,7 @@ import com.seibel.lod.core.api.internal.a7.ClientApi;
import com.seibel.lod.core.config.ConfigBase;
import com.seibel.lod.core.config.types.AbstractConfigType;
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import org.json.simple.JSONObject;
@@ -24,7 +24,7 @@ import java.nio.file.Path;
* @version 2022-5-26
*/
public class ConfigFileHandling {
public static final Path ConfigPath = SingletonHandler.INSTANCE.get(IMinecraftSharedWrapper.class).getInstallationDirectory().toPath().resolve("config").resolve(ModInfo.NAME+".toml");
public static final Path ConfigPath = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class).getInstallationDirectory().toPath().resolve("config").resolve(ModInfo.NAME+".toml");
/** Saves the config to the file */
public static void saveToFile() {
@@ -170,7 +170,7 @@ public class ConfigFileHandling {
} catch (IOException ex) {
System.out.println("Creating file failed");
ex.printStackTrace();
SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Loading file and resetting config file failed at path ["+ConfigPath+"]. Please check the file is ok and you have the permissions", ex);
SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).crashMinecraft("Loading file and resetting config file failed at path ["+ConfigPath+"]. Please check the file is ok and you have the permissions", ex);
}
}
}
@@ -22,7 +22,7 @@ package com.seibel.lod.core.handlers;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import org.apache.logging.log4j.Logger;
@@ -58,7 +58,7 @@ public class ReflectionHandler implements IReflectionHandler
@Override
public void finishDelayedSetup()
{
mcOptionsObject = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class).getOptionsObject();
mcOptionsObject = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getOptionsObject();
setupFogField(mcOptionsObject.getClass().getDeclaredFields());
this.delayedSetupDone = true;
@@ -1,164 +0,0 @@
/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2022 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.handlers.dependencyInjection;
import org.apache.logging.log4j.Logger;
import java.util.HashMap;
import java.util.Map;
/**
* This class takes care of tracking objects used in dependency injection.
*
* @param <BindableType> extends IBindable and defines what interfaces this dependency handler can deal with.
* @author James Seibel
* @version 2022-7-15
*/
public class DependencyHandler<BindableType extends IBindable>
{
protected final Logger logger;
protected final Map<Class<? extends BindableType>, Object> dependencies = new HashMap<Class<? extends BindableType>, Object>();
/** Internal class reference to BindableType since we can't get it any other way. */
protected final Class<? extends BindableType> bindableInterface;
public DependencyHandler(Class<BindableType> newBindableInterface, Logger newLogger)
{
this.bindableInterface = newBindableInterface;
this.logger = newLogger;
}
/**
* Links the given implementation object to an interface, so it can be referenced later.
*
* @param dependencyInterface The interface the implementation object should implement.
* @param dependencyImplementation An object that implements the dependencyInterface interface.
* @throws IllegalStateException if the implementation object doesn't implement
* the interface or the interface has already been bound.
*/
public void bind(Class<? extends BindableType> dependencyInterface, Object dependencyImplementation) throws IllegalStateException
{
// make sure we haven't already bound this dependency
if (dependencies.containsKey(dependencyInterface))
{
throw new IllegalStateException("The dependency [" + dependencyInterface.getSimpleName() + "] has already been bound.");
}
// make sure the given dependency implements the necessary interfaces
boolean implementsInterface = checkIfClassImplements(dependencyImplementation.getClass(), dependencyInterface);
boolean implementsBindable = checkIfClassImplements(dependencyImplementation.getClass(), this.bindableInterface);
// display any errors
if (!implementsInterface)
{
throw new IllegalStateException("The dependency [" + dependencyImplementation.getClass().getSimpleName() + "] doesn't implement the interface [" + dependencyInterface.getSimpleName() + "].");
}
if (!implementsBindable)
{
throw new IllegalStateException("The dependency [" + dependencyImplementation.getClass().getSimpleName() + "] doesn't implement the interface [" + IBindable.class.getSimpleName() + "].");
}
dependencies.put(dependencyInterface, dependencyImplementation);
}
/**
* Checks if classToTest (or one of its ancestors)
* implements the given interface.
*/
private boolean checkIfClassImplements(Class<?> classToTest, Class<?> interfaceToLookFor)
{
// check the parent class (if applicable)
if (classToTest.getSuperclass() != Object.class && classToTest.getSuperclass() != null)
{
if (checkIfClassImplements(classToTest.getSuperclass(), interfaceToLookFor))
{
return true;
}
}
// check interfaces
for (Class<?> implementationInterface : classToTest.getInterfaces())
{
// recurse to check interface parents if necessary
if (implementationInterface.getInterfaces().length != 0)
{
if (checkIfClassImplements(implementationInterface, interfaceToLookFor))
{
return true;
}
}
if (implementationInterface.equals(interfaceToLookFor))
{
return true;
}
}
return false;
}
/**
* Returns a dependency of type T if one has been bound.
* Returns null otherwise.
*
* @param <T> class of the dependency
* (inferred from the objectClass parameter)
* @param interfaceClass Interface of the dependency
* @return the dependency of type T
* @throws ClassCastException If the dependency isn't able to be cast to type T.
* (this shouldn't normally happen, unless the bound object changed somehow)
*/
@SuppressWarnings("unchecked")
public <T extends BindableType> T get(Class<?> interfaceClass) throws ClassCastException
{
T dependency = (T) dependencies.get(interfaceClass);
if (dependency != null && !dependency.getDelayedSetupComplete())
{
// a warning can be used here instead if desired
//this.logger.warn("Got dependency of type [" + interfaceClass.getSimpleName() + "], but the dependency's delayed setup hasn't been run!");
throw new IllegalStateException("Got dependency of type [" + interfaceClass.getSimpleName() + "], but the dependency's delayed setup hasn't been run!");
}
return dependency;
}
/** Runs delayed setup for any dependencies that require it. */
public void runDelayedSetup()
{
for (Class<?> interfaceKey : dependencies.keySet())
{
IBindable concreteObject = get(interfaceKey);
if (!concreteObject.getDelayedSetupComplete())
{
concreteObject.finishDelayedSetup();
}
}
}
}
@@ -0,0 +1,237 @@
/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2022 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.handlers.dependencyInjection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* This class takes care of tracking objects used in dependency injection.
*
* @param <BindableType> extends IBindable and defines what interfaces this dependency handler can deal with.
* @author James Seibel
* @version 2022-7-16
*/
public class DependencyInjector<BindableType extends IBindable>
{
protected final Map<Class<? extends BindableType>, ArrayList<BindableType>> dependencies = new HashMap<>();
/** Internal class reference to BindableType since we can't get it any other way. */
protected final Class<? extends BindableType> bindableInterface;
protected final boolean allowDuplicateBindings;
public DependencyInjector(Class<BindableType> newBindableInterface)
{
this.bindableInterface = newBindableInterface;
this.allowDuplicateBindings = false;
}
public DependencyInjector(Class<BindableType> newBindableInterface, boolean newAllowDuplicateBindings)
{
this.bindableInterface = newBindableInterface;
this.allowDuplicateBindings = newAllowDuplicateBindings;
}
/**
* Links the given implementation object to an interface, so it can be referenced later.
*
* @param dependencyInterface The interface (or parent class) the implementation object should implement.
* @param dependencyImplementation An object that implements the dependencyInterface interface.
* @throws IllegalStateException if the implementation object doesn't implement
* the interface or the interface has already been bound.
*/
public void bind(Class<? extends BindableType> dependencyInterface, BindableType dependencyImplementation) throws IllegalStateException
{
// duplicate check if requested
if (dependencies.containsKey(dependencyInterface) && !this.allowDuplicateBindings)
{
throw new IllegalStateException("The dependency [" + dependencyInterface.getSimpleName() + "] has already been bound.");
}
// make sure the given dependency implements the necessary interfaces
boolean implementsInterface = checkIfClassImplements(dependencyImplementation.getClass(), dependencyInterface)
|| checkIfClassExtends(dependencyImplementation.getClass(), dependencyInterface);
boolean implementsBindable = checkIfClassImplements(dependencyImplementation.getClass(), this.bindableInterface);
// display any errors
if (!implementsInterface)
{
throw new IllegalStateException("The dependency [" + dependencyImplementation.getClass().getSimpleName() + "] doesn't implement or extend: [" + dependencyInterface.getSimpleName() + "].");
}
if (!implementsBindable)
{
throw new IllegalStateException("The dependency [" + dependencyImplementation.getClass().getSimpleName() + "] doesn't implement the interface: [" + IBindable.class.getSimpleName() + "].");
}
// make sure the hashSet has an array to hold the dependency
if (!dependencies.containsKey(dependencyInterface))
{
dependencies.put(dependencyInterface, new ArrayList<BindableType>());
}
// add the dependency
dependencies.get(dependencyInterface).add(dependencyImplementation);
}
/**
* Checks if classToTest (or one of its ancestors)
* implements the given interface.
*/
protected boolean checkIfClassImplements(Class<?> classToTest, Class<?> interfaceToLookFor)
{
// check the parent class (if applicable)
if (classToTest.getSuperclass() != Object.class && classToTest.getSuperclass() != null)
{
if (checkIfClassImplements(classToTest.getSuperclass(), interfaceToLookFor))
{
return true;
}
}
// check interfaces
for (Class<?> implementationInterface : classToTest.getInterfaces())
{
// recurse to check interface parents if necessary
if (implementationInterface.getInterfaces().length != 0)
{
if (checkIfClassImplements(implementationInterface, interfaceToLookFor))
{
return true;
}
}
if (implementationInterface.equals(interfaceToLookFor))
{
return true;
}
}
return false;
}
/** Checks if classToTest extends the given class. */
protected boolean checkIfClassExtends(Class<?> classToTest, Class<?> extensionToLookFor)
{
return extensionToLookFor.isAssignableFrom(classToTest);
}
/**
* This does not return incomplete dependencies. <Br>
* See {@link #get(Class, boolean) get(Class, boolean)} for full documentation.
*
* @see #get(Class, boolean)
*/
@SuppressWarnings("unchecked")
public <T extends BindableType> T get(Class<?> interfaceClass) throws ClassCastException
{
return (T) getInternalLogic(interfaceClass, false).get(0);
}
/**
* Returns all dependencies of type T that have been bound. <br>
* Returns an empty list if no dependencies have been bound.
*
* @param <T> class of the dependency
* (inferred from the objectClass parameter)
* @param interfaceClass Interface of the dependency
* @return the dependency of type T
* @throws ClassCastException If the dependency isn't able to be cast to type T.
* (this shouldn't normally happen, unless the bound object changed somehow)
*/
public <T extends BindableType> ArrayList<T> getAll(Class<?> interfaceClass) throws ClassCastException
{
return getInternalLogic(interfaceClass, false);
}
/**
* Returns a dependency of type T if one has been bound. <br>
* Returns null if a dependency hasn't been bound. <br> <br>
*
* If the handler's {@link #allowDuplicateBindings} is true this returns the first bound dependency.
*
* @param <T> class of the dependency
* (inferred from the objectClass parameter)
* @param interfaceClass Interface of the dependency
* @param allowIncompleteDependencies If true this method will also return dependencies that haven't completed their delayed setup.
* @return the dependency of type T
* @throws ClassCastException If the dependency isn't able to be cast to type T.
* (this shouldn't normally happen, unless the bound object changed somehow)
*/
@SuppressWarnings("unchecked")
public <T extends BindableType> T get(Class<?> interfaceClass, boolean allowIncompleteDependencies) throws ClassCastException
{
return (T) getInternalLogic(interfaceClass, allowIncompleteDependencies).get(0);
}
/**
* Always returns a list of size 1 or greater,
* if no dependencies have been bound the list will contain null.
*/
@SuppressWarnings("unchecked")
private <T extends BindableType> ArrayList<T> getInternalLogic(Class<?> interfaceClass, boolean allowIncompleteDependencies) throws ClassCastException
{
ArrayList<BindableType> dependencyList = dependencies.get(interfaceClass);
if (dependencyList != null && dependencyList.size() != 0)
{
// check if each dependencies' delayed setup has been completed
for (IBindable dependency : dependencyList)
{
if (!dependency.getDelayedSetupComplete() && !allowIncompleteDependencies)
{
// a warning can be used here instead if desired
//this.logger.warn("Got dependency of type [" + interfaceClass.getSimpleName() + "], but the dependency's delayed setup hasn't been run!");
throw new IllegalStateException("Got dependency of type [" + interfaceClass.getSimpleName() + "], but the dependency's delayed setup hasn't been run!");
}
}
return (ArrayList<T>) dependencyList;
}
// return an empty list to prevent null pointers
ArrayList<T> emptyList = new ArrayList<T>();
emptyList.add(null);
return emptyList;
}
/** Runs delayed setup for any dependencies that require it. */
public void runDelayedSetup()
{
for (Class<?> interfaceKey : dependencies.keySet())
{
IBindable concreteObject = get(interfaceKey, true);
if (!concreteObject.getDelayedSetupComplete())
{
concreteObject.finishDelayedSetup();
}
}
}
}
@@ -0,0 +1,131 @@
/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2022 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.core.handlers.dependencyInjection;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
import java.util.ArrayList;
/**
* This class takes care of dependency injection for mods accessors. (for mod compatibility
* support). <Br> <Br>
*
* If a IModAccessor returns null either that means the mod isn't loaded in the game
* or an Accessor hasn't been implemented for the given Minecraft version.
*
* @author James Seibel
* @author Leetom
* @version 2022-7-16
*/
public class DhApiEventInjector extends DependencyInjector<IDhApiEvent>
{
public static final DhApiEventInjector INSTANCE = new DhApiEventInjector();
public DhApiEventInjector()
{
super(IDhApiEvent.class, true);
}
/**
* Unlinks the given event handler, preventing the handler from being called in the future.
*
* @param dependencyInterface The interface the event handler implements.
* @return true if the handler was unbound, false if the handler wasn't bound.
*/
public boolean unbind(Class<? extends IDhApiEvent> dependencyInterface, Class<? extends IDhApiEvent> dependencyClassToRemove)
{
// make sure the given dependency implements the necessary interfaces
boolean implementsInterface = checkIfClassImplements(dependencyClassToRemove, dependencyInterface)
|| checkIfClassExtends(dependencyClassToRemove, dependencyInterface);
boolean implementsBindable = checkIfClassImplements(dependencyClassToRemove, this.bindableInterface);
// display any errors
if (!implementsInterface)
{
throw new IllegalStateException("The event handler [" + dependencyClassToRemove.getSimpleName() + "] doesn't implement or extend: [" + dependencyInterface.getSimpleName() + "].");
}
if (!implementsBindable)
{
throw new IllegalStateException("The event handler [" + dependencyClassToRemove.getSimpleName() + "] doesn't implement the interface: [" + IBindable.class.getSimpleName() + "].");
}
// actually remove the dependency
if (this.dependencies.containsKey(dependencyInterface))
{
ArrayList<IDhApiEvent> dependencyList = this.dependencies.get(dependencyInterface);
int indexToRemove = -1;
for(int i = 0; i < dependencyList.size(); i++)
{
IBindable dependency = dependencyList.get(i);
if (dependency.getClass().equals(dependencyClassToRemove))
{
indexToRemove = i;
break;
}
}
if (indexToRemove != -1)
{
return dependencyList.remove(indexToRemove) != null;
}
}
// no item was removed
return false;
}
/**
* Fires all bound events of the given type (does nothing if no events are bound).
*
* @param dependencyInterface event type
* @param eventParameterObject event parameter
* @return if any of the events returned that this event should be canceled.
* @param <T> the parameter type taken by the event handlers.
*/
public <T> boolean fireAllEvents(Class<? extends IDhApiEvent<T>> dependencyInterface, T eventParameterObject)
{
boolean cancelEvent = false;
ArrayList<IDhApiEvent<T>> eventList = this.getAll(dependencyInterface);
for (IDhApiEvent<T> event : eventList)
{
if (event != null)
{
try
{
// fire each event and record if any of them
// request to cancel the event.
cancelEvent |= event.onEvent(eventParameterObject);
}
catch (Exception e)
{
// TODO log the failed event handler
System.out.println("Exception thrown by event handler :" + e.getMessage());
}
}
}
return cancelEvent;
}
}
@@ -23,7 +23,7 @@ package com.seibel.lod.core.handlers.dependencyInjection;
* Necessary for all singletons that can be dependency injected.
*
* @author James Seibel
* @version 3-4-2022
* @version 2022-7-16
*/
public interface IBindable
{
@@ -34,30 +34,30 @@ import java.lang.invoke.MethodHandles;
*
* @author James Seibel
* @author Leetom
* @version 2022-7-15
* @version 2022-7-16
*/
public class ModAccessorHandler extends DependencyHandler<IModAccessor>
public class ModAccessorInjector extends DependencyInjector<IModAccessor>
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
public static final ModAccessorHandler INSTANCE = new ModAccessorHandler(IModAccessor.class, LOGGER);
public static final ModAccessorInjector INSTANCE = new ModAccessorInjector(IModAccessor.class);
public ModAccessorHandler(Class<IModAccessor> newBindableInterface, Logger newLogger)
public ModAccessorInjector(Class<IModAccessor> newBindableInterface)
{
super(newBindableInterface, LOGGER);
super(newBindableInterface, false);
}
/**
* Go to {@link DependencyHandler#bind(Class, Object) DependencyHandler.bind()}
* Go to {@link DependencyInjector#bind(Class, IBindable)} DependencyHandler.bind()}
* for this method's javadocs.
*/
public void bind(Class<? extends IModAccessor> interfaceClass, IModAccessor modAccessor)
throws IllegalStateException
{
super.bind(interfaceClass, modAccessor);
LOGGER.info("Registered mod compatibility accessor for " + modAccessor.getModName());
LOGGER.info("Registered mod compatibility accessor for: [" + modAccessor.getModName() + "].");
}
}
@@ -19,28 +19,18 @@
package com.seibel.lod.core.handlers.dependencyInjection;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModAccessor;
import org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandles;
/**
* This class takes care of dependency injection
* for singletons.
*
* @author James Seibel
* @version 2022-7-15
* @version 2022-7-16
*/
public class SingletonHandler extends DependencyHandler<IBindable>
public class SingletonInjector extends DependencyInjector<IBindable>
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
public static final SingletonHandler INSTANCE = new SingletonHandler(IBindable.class, LOGGER);
public static final SingletonInjector INSTANCE = new SingletonInjector(IBindable.class);
public SingletonHandler(Class<IBindable> newBindableInterface, Logger newLogger)
{
super(newBindableInterface, newLogger);
}
public SingletonInjector(Class<IBindable> newBindableInterface) { super(newBindableInterface, false); }
}
@@ -21,11 +21,10 @@ package com.seibel.lod.core.handlers.dimensionFinder;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.DHBlockPos;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import org.lwjgl.system.CallbackI;
import javax.annotation.Nullable;
import java.io.File;
@@ -38,7 +37,7 @@ import java.io.File;
*/
public class PlayerData
{
public static final IWrapperFactory FACTORY = SingletonHandler.INSTANCE.get(IWrapperFactory.class);
public static final IWrapperFactory FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
private static final String playerDataFileName = "_playerData.toml";
@@ -1,12 +1,12 @@
package com.seibel.lod.core.jar;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.jar.wrapperInterfaces.config.ConfigWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.IConfigWrapper;
public class JarDependencySetup {
public static void createInitialBindings() {
SingletonHandler.INSTANCE.bind(IConfigWrapper.class, ConfigWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IConfigWrapper.class, ConfigWrapper.INSTANCE);
ConfigWrapper.init();
}
}
@@ -4,7 +4,7 @@ import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.seibel.lod.core.JarMain;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.wrapperInterfaces.config.IConfigWrapper;
import javax.imageio.ImageIO;
@@ -33,7 +33,7 @@ public class BaseJFrame extends JFrame {
}
public void init() {
setTitle(SingletonHandler.INSTANCE.get(IConfigWrapper.class).getLang("lod.title"));
setTitle(SingletonInjector.INSTANCE.get(IConfigWrapper.class).getLang("lod.title"));
try {
setIconImage(new FlatSVGIcon(JarMain.accessFile("icon.svg")).getImage());
} catch (Exception e) {e.printStackTrace();}
@@ -28,7 +28,7 @@ import com.seibel.lod.core.enums.config.EDistanceGenerationMode;
import com.seibel.lod.core.enums.config.EDropoffQuality;
import com.seibel.lod.core.enums.config.EGenerationPriority;
import com.seibel.lod.core.enums.config.EVerticalQuality;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.*;
import com.seibel.lod.core.util.DataPointUtil;
import com.seibel.lod.core.util.DetailDistanceUtil;
@@ -50,7 +50,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
* @version 10-10-2021
*/
public class LodRegion {
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.INSTANCE.get(ILodConfigWrapperSingleton.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonInjector.INSTANCE.get(ILodConfigWrapperSingleton.class);
/** Number of detail level supported by a region */
private static final byte POSSIBLE_LOD = LodUtil.DETAIL_OPTIONS;
@@ -332,7 +332,7 @@ public class LodRegion {
private EGenerationPriority getResolvedGenerationPriority() {
EGenerationPriority priority = Config.Client.WorldGenerator.generationPriority.get();
IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
if (priority == EGenerationPriority.AUTO)
priority = MC.hasSinglePlayerServer() ? EGenerationPriority.FAR_FIRST : EGenerationPriority.BALANCED;
return priority;
@@ -26,7 +26,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.LodDataView;
import com.seibel.lod.core.util.*;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -68,7 +68,7 @@ public class VerticalLevelContainer implements LevelContainer
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
verticalSize = DetailDistanceUtil.getMaxVerticalData(detailLevel);
dataContainer = new long[size * size * DetailDistanceUtil.getMaxVerticalData(detailLevel)];
minHeight = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
minHeight = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
}
@Override
@@ -319,7 +319,7 @@ public class VerticalLevelContainer implements LevelContainer
}
public VerticalLevelContainer(DataInputStream inputData, int version, byte expectedDetailLevel) throws IOException {
minHeight = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
minHeight = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
detailLevel = inputData.readByte();
if (detailLevel != expectedDetailLevel)
throw new IOException("Invalid Data: The expected detail level should be "+expectedDetailLevel+
@@ -21,7 +21,7 @@ package com.seibel.lod.core.objects.opengl;
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodQuadBuilder;
import com.seibel.lod.core.enums.ELodDirection;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.LodDataView;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.util.DataPointUtil;
@@ -29,7 +29,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
public class LodBox
{
private static final IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public static void addBoxQuadsToBuilder(LodQuadBuilder builder, short xSize, short ySize, short zSize, short x,
short y, short z, int color, byte skyLight, byte blockLight, long topData, long botData, LodDataView[][] adjData,
@@ -42,7 +42,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.enums.config.EGpuUploadMethod;
import com.seibel.lod.core.enums.rendering.EGLProxyContext;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.util.GLMessage;
import com.seibel.lod.core.util.GLMessageOutputStream;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -68,7 +68,7 @@ public class GLProxy
{
public static final boolean OVERRIDE_VANILLA_GL_LOGGER = ModInfo.IS_DEV_BUILD;
private static final IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private ExecutorService workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build());
@@ -24,7 +24,7 @@ import com.seibel.lod.core.enums.rendering.EFogDrawMode;
import com.seibel.lod.core.enums.rendering.EFogDistance;
import com.seibel.lod.core.enums.rendering.*;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.FogSettings;
import com.seibel.lod.core.render.objects.Shader;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
@@ -46,8 +46,8 @@ import static com.seibel.lod.core.render.GLProxy.GL_LOGGER;
*/
public class LodFogConfig
{
private static final IReflectionHandler REFLECTION_HANDLER = SingletonHandler.INSTANCE.get(IReflectionHandler.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.INSTANCE.get(ILodConfigWrapperSingleton.class);
private static final IReflectionHandler REFLECTION_HANDLER = SingletonInjector.INSTANCE.get(IReflectionHandler.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonInjector.INSTANCE.get(ILodConfigWrapperSingleton.class);
public static final boolean DEBUG_DUMP_GENERATED_CODE = false;
@@ -21,7 +21,7 @@ package com.seibel.lod.core.render;
import java.awt.Color;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.render.objects.*;
@@ -32,7 +32,7 @@ public class LodRenderProgram extends ShaderProgram {
public static final String VERTEX_SHADER_PATH = "shaders/standard.vert";
public static final String VERTEX_CURVE_SHADER_PATH = "shaders/curve.vert";
public static final String FRAGMENT_SHADER_PATH = "shaders/flat_shaded.frag";
private static final IVersionConstants VERSION_CONSTANTS = SingletonHandler.INSTANCE.get(IVersionConstants.class);
private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class);
public final VertexAttribute vao;
@@ -21,7 +21,7 @@ package com.seibel.lod.core.render;
import com.seibel.lod.core.enums.config.EGpuUploadMethod;
import com.seibel.lod.core.enums.config.ELoggerMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
@@ -45,7 +45,7 @@ public class RenderSystemTest {
LogManager.getLogger(RenderSystemTest.class), () -> ELoggerMode.LOG_ALL_TO_CHAT);
public static final ConfigBasedSpamLogger spamLogger = new ConfigBasedSpamLogger(
LogManager.getLogger(RenderSystemTest.class), () -> ELoggerMode.LOG_ALL_TO_CHAT, 1);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
ShaderProgram basicShader;
GLVertexBuffer sameContextBuffer;
@@ -19,7 +19,7 @@
package com.seibel.lod.core.render;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.DHBlockPos;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.objects.math.Vec3f;
@@ -35,7 +35,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
*/
public class RenderUtil
{
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
/**
@@ -25,11 +25,10 @@ import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodBufferBuilderF
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.core.enums.rendering.EDebugMode;
import com.seibel.lod.core.enums.rendering.EFogColorMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
import com.seibel.lod.core.objects.DHBlockPos;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.render.RenderBufferHandler;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
@@ -79,8 +78,8 @@ public class a7LodRenderer
}
}
private static final IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
public EDebugMode previousDebugMode = null;
public final IClientLevel level;
@@ -19,9 +19,6 @@
package com.seibel.lod.core.util;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
/**
*
* @author Cola
@@ -27,7 +27,7 @@ import java.util.concurrent.Executors;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.config.EServerFolderNameMode;
import com.seibel.lod.core.enums.config.EVanillaOverdraw;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.objects.ParsedIp;
import com.seibel.lod.core.objects.Pos2D;
@@ -48,8 +48,8 @@ import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
*/
public class LodUtil
{
private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
/**
* Vanilla render distances less than or equal to this will not allow partial
@@ -27,7 +27,7 @@ import com.seibel.lod.core.enums.rendering.ERendererMode;
import com.seibel.lod.core.enums.config.*;
import com.seibel.lod.core.enums.rendering.*;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.FogSettings;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -264,7 +264,7 @@ public interface ILodConfigWrapperSingleton extends IBindable
default EGenerationPriority getResolvedGenerationPriority() {
EGenerationPriority priority = Config.Client.WorldGenerator.generationPriority.get();
IMinecraftClientWrapper MC = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
if (priority == EGenerationPriority.AUTO)
priority = MC.hasSinglePlayerServer() ? EGenerationPriority.FAR_FIRST : EGenerationPriority.BALANCED;
return priority;
@@ -23,8 +23,8 @@ import java.awt.Color;
import java.util.HashSet;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorInjector;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.DHBlockPos;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.objects.math.Mat4f;
@@ -85,7 +85,7 @@ public interface IMinecraftRenderWrapper extends IBindable
*/
default HashSet<DHChunkPos> getVanillaRenderedChunks()
{
ISodiumAccessor sodium = ModAccessorHandler.INSTANCE.get(ISodiumAccessor.class);
ISodiumAccessor sodium = ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
return sodium==null ? getMaximumRenderedChunks() : sodium.getNormalRenderedChunks();
}
@@ -101,10 +101,10 @@ public interface IMinecraftRenderWrapper extends IBindable
*/
default HashSet<DHChunkPos> getMaximumRenderedChunks()
{
IMinecraftClientWrapper mcWrapper = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
IWrapperFactory factory = SingletonHandler.INSTANCE.get(IWrapperFactory.class);
IVersionConstants versionConstants = SingletonHandler.INSTANCE.get(IVersionConstants.class);
IMinecraftClientWrapper minecraft = SingletonHandler.INSTANCE.get(IMinecraftClientWrapper.class);
IMinecraftClientWrapper mcWrapper = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
IWrapperFactory factory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
IVersionConstants versionConstants = SingletonInjector.INSTANCE.get(IVersionConstants.class);
IMinecraftClientWrapper minecraft = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
ILevelWrapper clientWorld = minecraft.getWrappedClientWorld();
int chunkDist = this.getRenderDistance() + 1; // For some reason having '+1' is actually closer to real value
@@ -0,0 +1,25 @@
package testItems.dependencyInjection.implementations;
import testItems.dependencyInjection.objects.DhApiTestEvent;
/**
* Dummy test event for unit tests.
*
* @author James Seibel
* @version 2022-7-16
*/
public class DhTestEvent extends DhApiTestEvent
{
public Boolean eventFiredValue = null;
@Override
public boolean test(Boolean cancelEvent)
{
this.eventFiredValue = cancelEvent;
return cancelEvent;
}
@Override
public Boolean getTestValue() { return this.eventFiredValue; }
}
@@ -0,0 +1,25 @@
package testItems.dependencyInjection.implementations;
import testItems.dependencyInjection.objects.DhApiTestEvent;
/**
* Dummy test event for unit tests.
*
* @author James Seibel
* @version 2022-7-16
*/
public class DhTestEventAlt extends DhApiTestEvent
{
public Boolean eventFiredValue = null;
@Override
public boolean test(Boolean cancelEvent)
{
this.eventFiredValue = cancelEvent;
return cancelEvent;
}
@Override
public Boolean getTestValue() { return this.eventFiredValue; }
}
@@ -0,0 +1,16 @@
package testItems.dependencyInjection.interfaces;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
/**
* Dummy test interface for dependency unit tests.
*
* @author James Seibel
* @version 2022-7-16
*/
public interface ITestOne extends IBindable
{
public int getValue();
public int getDependentValue();
}
@@ -0,0 +1,16 @@
package testItems.dependencyInjection.interfaces;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
/**
* Dummy test interface for dependency unit tests.
*
* @author James Seibel
* @version 2022-7-16
*/
public interface ITestTwo extends IBindable
{
public int getValue();
public int getDependentValue();
}
@@ -0,0 +1,28 @@
package testItems.dependencyInjection.objects;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
import testItems.dependencyInjection.interfaces.ITestOne;
import testItems.dependencyInjection.interfaces.ITestTwo;
/**
* Dummy test implementation object for dependency injection unit tests.
*
* @author James Seibel
* @version 2022-7-16
*/
public class ConcreteTestBoth implements ITestOne, ITestTwo, IBindable
{
public static final int VALUE = 3;
@Override
public void finishDelayedSetup() { }
@Override
public int getValue()
{
return VALUE;
}
@Override
public int getDependentValue() { return -1; }
}
@@ -0,0 +1,34 @@
package testItems.dependencyInjection.objects;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
import testItems.dependencyInjection.interfaces.ITestOne;
import testItems.dependencyInjection.interfaces.ITestTwo;
import tests.DependencyInjectorTest;
/**
* Dummy test implementation object for dependency injection unit tests.
*
* @author James Seibel
* @version 2022-7-16
*/
public class ConcreteTestOne implements ITestOne, IBindable
{
private ITestTwo testInterTwo;
public static int VALUE = 1;
@Override
public void finishDelayedSetup() { testInterTwo = DependencyInjectorTest.TEST_SINGLETON_HANDLER.get(ITestTwo.class, true); }
@Override
public boolean getDelayedSetupComplete() { return testInterTwo != null; }
@Override
public int getValue() { return VALUE; }
@Override
public int getDependentValue() { return testInterTwo.getValue(); }
}
@@ -0,0 +1,34 @@
package testItems.dependencyInjection.objects;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
import testItems.dependencyInjection.interfaces.ITestOne;
import testItems.dependencyInjection.interfaces.ITestTwo;
import tests.DependencyInjectorTest;
/**
* Dummy test implementation object for dependency injection unit tests.
*
* @author James Seibel
* @version 2022-7-16
*/
public class ConcreteTestTwo implements ITestTwo, IBindable
{
private ITestOne testInterOne;
public static int VALUE = 2;
@Override
public void finishDelayedSetup() { testInterOne = DependencyInjectorTest.TEST_SINGLETON_HANDLER.get(ITestOne.class, true); }
@Override
public boolean getDelayedSetupComplete() { return testInterOne != null; }
@Override
public int getValue() { return VALUE; }
@Override
public int getDependentValue() { return testInterOne.getValue(); }
}
@@ -0,0 +1,40 @@
package testItems.dependencyInjection.objects;
import com.seibel.lod.core.api.implementation.interfaces.events.IDhApiEvent;
/**
* A dummy event implementation used for unit testing.
*
* @author James Seibel
* @version 2022-7-16
*/
public abstract class DhApiTestEvent implements IDhApiEvent<Boolean>
{
/**
* Test event.
*
* @param input
* @return whether the event should be canceled or not.
*/
public abstract boolean test(Boolean input);
/**
* Normal DhApiEvent classes shouldn't have any other methods like this.
* This is just for testing.
*/
public abstract Boolean getTestValue();
//=========================//
// internal DH API methods //
//=========================//
@Override
public final boolean onEvent(Boolean input)
{
return test(input);
}
@Override
public final boolean getCancelable() { return true; }
}
@@ -1,4 +1,4 @@
/*
package tests;/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*
@@ -0,0 +1,160 @@
package tests;
import com.seibel.lod.core.handlers.dependencyInjection.DependencyInjector;
import com.seibel.lod.core.handlers.dependencyInjection.DhApiEventInjector;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
import org.junit.Assert;
import org.junit.Test;
import testItems.dependencyInjection.implementations.DhTestEvent;
import testItems.dependencyInjection.implementations.DhTestEventAlt;
import testItems.dependencyInjection.interfaces.ITestOne;
import testItems.dependencyInjection.interfaces.ITestTwo;
import testItems.dependencyInjection.objects.ConcreteTestBoth;
import testItems.dependencyInjection.objects.ConcreteTestOne;
import testItems.dependencyInjection.objects.ConcreteTestTwo;
import testItems.dependencyInjection.objects.DhApiTestEvent;
import java.util.ArrayList;
/**
* @author James Seibel
* @version 7-16-2022
*/
public class DependencyInjectorTest
{
public static DependencyInjector<IBindable> TEST_SINGLETON_HANDLER;
public static DhApiEventInjector TEST_EVENT_HANDLER;
@Test
public void testSingleImplementations()
{
// clear the previous dependencies and only allow single dependencies
TEST_SINGLETON_HANDLER = new DependencyInjector<>(IBindable.class, false);
// pre-setup
Assert.assertNull(ITestOne.class.getSimpleName() + " should not have been bound.", TEST_SINGLETON_HANDLER.get(ITestOne.class));
// dependency setup
TEST_SINGLETON_HANDLER.bind(ITestOne.class, new ConcreteTestOne());
TEST_SINGLETON_HANDLER.bind(ITestTwo.class, new ConcreteTestTwo());
TEST_SINGLETON_HANDLER.runDelayedSetup();
// basic dependencies
ITestOne testInterOne = TEST_SINGLETON_HANDLER.get(ITestOne.class);
Assert.assertNotNull(ITestOne.class.getSimpleName() + " not bound.", testInterOne);
Assert.assertEquals(ITestOne.class.getSimpleName() + " incorrect value.", testInterOne.getValue(), ConcreteTestOne.VALUE);
ITestTwo testInterTwo = TEST_SINGLETON_HANDLER.get(ITestTwo.class);
Assert.assertNotNull(ITestTwo.class.getSimpleName() + " not bound.", testInterTwo);
Assert.assertEquals(ITestTwo.class.getSimpleName() + " incorrect value.", testInterTwo.getValue(), ConcreteTestTwo.VALUE);
// circular dependencies (if this throws an exception the dependency isn't set up)
Assert.assertEquals(ITestOne.class.getSimpleName() + " incorrect value.", testInterOne.getDependentValue(), ConcreteTestTwo.VALUE);
Assert.assertEquals(ITestTwo.class.getSimpleName() + " incorrect value.", testInterTwo.getDependentValue(), ConcreteTestOne.VALUE);
}
@Test
public void testMultipleImplementations()
{
// clear the previous dependencies and only allow single dependencies
TEST_SINGLETON_HANDLER = new DependencyInjector<IBindable>(IBindable.class, false);
// pre-setup
Assert.assertNull(ITestOne.class.getSimpleName() + " should not have been bound.", TEST_SINGLETON_HANDLER.get(ITestOne.class));
// dependency setup
ConcreteTestBoth concreteInstance = new ConcreteTestBoth();
TEST_SINGLETON_HANDLER.bind(ITestOne.class, concreteInstance);
TEST_SINGLETON_HANDLER.bind(ITestTwo.class, concreteInstance);
// basic dependencies
ITestOne testInterOne = TEST_SINGLETON_HANDLER.get(ITestOne.class);
Assert.assertNotNull(ITestOne.class.getSimpleName() + " not bound.", testInterOne);
Assert.assertEquals(ITestOne.class.getSimpleName() + " incorrect value.", testInterOne.getValue(), ConcreteTestBoth.VALUE);
ITestTwo testInterTwo = TEST_SINGLETON_HANDLER.get(ITestTwo.class);
Assert.assertNotNull(ITestTwo.class.getSimpleName() + " not bound.", testInterTwo);
Assert.assertEquals(ITestTwo.class.getSimpleName() + " incorrect value.", testInterTwo.getValue(), ConcreteTestBoth.VALUE);
}
@Test
public void testEventDependencies() // this also tests list dependencies since there can be more than one event handler bound per event
{
// clear the previous dependencies and only allow single dependencies
TEST_SINGLETON_HANDLER = new DependencyInjector<>(IBindable.class, false);
// setup the list (event) dependency handler
TEST_EVENT_HANDLER = new DhApiEventInjector();
// pre-setup
Assert.assertNull("Nothing should have been bound.", TEST_EVENT_HANDLER.get(DhApiTestEvent.class));
// dependency setup
TEST_EVENT_HANDLER.bind(DhApiTestEvent.class, new DhTestEvent());
TEST_EVENT_HANDLER.bind(DhApiTestEvent.class, new DhTestEventAlt());
TEST_EVENT_HANDLER.runDelayedSetup();
// get first
DhApiTestEvent afterRenderEvent = TEST_EVENT_HANDLER.get(DhApiTestEvent.class);
Assert.assertNotNull("Event not bound.", afterRenderEvent);
// get list
ArrayList<DhApiTestEvent> afterRenderEventList = TEST_EVENT_HANDLER.getAll(DhApiTestEvent.class);
Assert.assertEquals("Bound list doesn't contain the correct number of items.", 2, afterRenderEventList.size());
// object one
Assert.assertNotNull("Event not bound.", afterRenderEventList.get(0));
Assert.assertEquals("First event object setup incorrectly.", null, afterRenderEventList.get(0).getTestValue());
// object two
Assert.assertNotNull("Event not bound.", afterRenderEventList.get(1));
Assert.assertEquals("First event object setup incorrectly.", null, afterRenderEventList.get(1).getTestValue());
// event firing
Assert.assertEquals("fireAllEvents canceled returned canceled incorrectly.", true, TEST_EVENT_HANDLER.fireAllEvents(DhApiTestEvent.class, true));
// object one
Assert.assertEquals("Event not fired for first object.", true, afterRenderEventList.get(0).getTestValue());
// object two
Assert.assertEquals("Event not fired for second object.", true, afterRenderEventList.get(1).getTestValue());
// unbind
DhApiTestEvent unboundEvent = afterRenderEventList.get(0);
Assert.assertTrue("Unbind should've removed item.", TEST_EVENT_HANDLER.unbind(DhApiTestEvent.class, DhTestEvent.class));
Assert.assertFalse("Unbind should've already removed item.", TEST_EVENT_HANDLER.unbind(DhApiTestEvent.class, DhTestEvent.class));
// check unbinding
afterRenderEventList = TEST_EVENT_HANDLER.getAll(DhApiTestEvent.class);
Assert.assertEquals("Unbound list doesn't contain the correct number of items.", 1, afterRenderEventList.size());
Assert.assertNotNull("Unbinding removed all items.", afterRenderEventList.get(0));
// check unbound event firing
Assert.assertEquals("fireAllEvents canceled returned canceled incorrectly.", false, TEST_EVENT_HANDLER.fireAllEvents(DhApiTestEvent.class, false));
// remaining event
Assert.assertEquals("Event not fired for remaining object.", false, ((DhTestEventAlt) afterRenderEventList.get(0)).eventFiredValue);
// unbound event
Assert.assertEquals("Event fired for unbound object.", true, unboundEvent.getTestValue());
}
}
@@ -1,4 +1,4 @@
/*
package tests;/*
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
* licensed under the GNU LGPL v3 License.
*