diff --git a/src/main/java/com/seibel/lod/core/api/external/items/enums/DhApiEnumAssembly.java b/src/main/java/com/seibel/lod/core/api/external/items/enums/DhApiEnumAssembly.java
index a66c354fb..3b48c2d65 100644
--- a/src/main/java/com/seibel/lod/core/api/external/items/enums/DhApiEnumAssembly.java
+++ b/src/main/java/com/seibel/lod/core/api/external/items/enums/DhApiEnumAssembly.java
@@ -19,6 +19,7 @@
package com.seibel.lod.core.api.external.items.enums;
+import com.seibel.lod.core.api.external.items.enums.override.DhApiOverrideEnumAssembly;
import com.seibel.lod.core.api.external.items.enums.config.DhApiConfigEnumAssembly;
import com.seibel.lod.core.api.external.items.enums.worldGeneration.DhApiWorldGenerationEnumAssembly;
@@ -26,7 +27,7 @@ import com.seibel.lod.core.api.external.items.enums.worldGeneration.DhApiWorldGe
* Assembly classes are used to reference the package they are in.
*
* @author James Seibel
- * @version 2022-7-14
+ * @version 2022-7-18
*/
public class DhApiEnumAssembly
{
@@ -34,6 +35,7 @@ public class DhApiEnumAssembly
// This is done so they can be found via reflection.
private static final DhApiWorldGenerationEnumAssembly worldGenerationAssembly = new DhApiWorldGenerationEnumAssembly();
private static final DhApiConfigEnumAssembly configAssembly = new DhApiConfigEnumAssembly();
+ private static final DhApiOverrideEnumAssembly overrideAssembly = new DhApiOverrideEnumAssembly();
/** All DH API enums should have this prefix */
public static final String API_ENUM_PREFIX = "EDhApi";
diff --git a/src/main/java/com/seibel/lod/core/api/external/items/enums/override/DhApiOverrideEnumAssembly.java b/src/main/java/com/seibel/lod/core/api/external/items/enums/override/DhApiOverrideEnumAssembly.java
new file mode 100644
index 000000000..d6763a75d
--- /dev/null
+++ b/src/main/java/com/seibel/lod/core/api/external/items/enums/override/DhApiOverrideEnumAssembly.java
@@ -0,0 +1,31 @@
+/*
+ * 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 .
+ */
+
+package com.seibel.lod.core.api.external.items.enums.override;
+
+/**
+ * Assembly classes are used to reference the package they are in.
+ *
+ * @author James Seibel
+ * @version 2022-7-16
+ */
+public class DhApiOverrideEnumAssembly
+{
+
+}
diff --git a/src/main/java/com/seibel/lod/core/api/external/items/enums/override/EDhApiOverridePriority.java b/src/main/java/com/seibel/lod/core/api/external/items/enums/override/EDhApiOverridePriority.java
new file mode 100644
index 000000000..12af4da0b
--- /dev/null
+++ b/src/main/java/com/seibel/lod/core/api/external/items/enums/override/EDhApiOverridePriority.java
@@ -0,0 +1,34 @@
+package com.seibel.lod.core.api.external.items.enums.override;
+
+/**
+ * PRIMARY,
+ * SECONDARY,
+ * CORE,
+ *
+ * @author James Seibel
+ * @version 2022-7-18
+ */
+public enum EDhApiOverridePriority
+{
+ /**
+ * The default Override priority and the one generally suggested
+ * for developers who want to create an override.
+ * The highest priority.
+ */
+ PRIMARY,
+
+ /**
+ * Overrides with this priority are only used if there isn't
+ * an override with PRIMARY priority.
+ * Could be used to allow creating overrides that other mod developers
+ * could override.
+ */
+ SECONDARY,
+
+ /**
+ * Only Distant Horizons classes should use the CORE priority,
+ * attempting to set an override with CORE priority will result in an error.
+ * This is the lowest priority and will be overridden by all other priorities.
+ */
+ CORE,
+}
diff --git a/src/main/java/com/seibel/lod/core/api/external/items/interfaces/override/IDhApiOverrideable.java b/src/main/java/com/seibel/lod/core/api/external/items/interfaces/override/IDhApiOverrideable.java
index 46f42d11e..b04ec2511 100644
--- a/src/main/java/com/seibel/lod/core/api/external/items/interfaces/override/IDhApiOverrideable.java
+++ b/src/main/java/com/seibel/lod/core/api/external/items/interfaces/override/IDhApiOverrideable.java
@@ -1,11 +1,20 @@
package com.seibel.lod.core.api.external.items.interfaces.override;
+import com.seibel.lod.core.api.external.items.enums.override.EDhApiOverridePriority;
+import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
+
/**
* Implemented by all DhApi objects that can be overridden.
*
* @author James Seibel
- * @version 2022-7-14
+ * @version 2022-7-18
*/
-public interface IDhApiOverrideable
+public interface IDhApiOverrideable extends IBindable
{
+ /**
+ * Returns when this Override should be used.
+ * For most developers this can be left at the default.
+ */
+ default EDhApiOverridePriority getOverrideType() { return EDhApiOverridePriority.PRIMARY; }
+
}
diff --git a/src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java b/src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java
index eb384190e..b60827e76 100644
--- a/src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java
+++ b/src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java
@@ -20,13 +20,14 @@
package com.seibel.lod.core.enums;
import com.seibel.lod.core.enums.config.CoreConfigEnumAssembly;
+import com.seibel.lod.core.enums.override.CoreOverrideEnumAssembly;
import com.seibel.lod.core.enums.rendering.CoreRenderingEnumAssembly;
/**
* Assembly classes are used to reference the package they are in.
*
* @author James Seibel
- * @version 2022-6-9
+ * @version 2022-7-18
*/
public class CoreEnumAssembly
{
@@ -34,6 +35,7 @@ public class CoreEnumAssembly
// This is done so they can be found via reflection.
private static final CoreRenderingEnumAssembly renderingAssembly = new CoreRenderingEnumAssembly();
private static final CoreConfigEnumAssembly configAssembly = new CoreConfigEnumAssembly();
+ private static final CoreOverrideEnumAssembly overrideAssembly = new CoreOverrideEnumAssembly();
/** All enums should have this prefix */
public static final String ENUM_PREFIX = "E";
diff --git a/src/main/java/com/seibel/lod/core/enums/override/CoreOverrideEnumAssembly.java b/src/main/java/com/seibel/lod/core/enums/override/CoreOverrideEnumAssembly.java
new file mode 100644
index 000000000..4122126ee
--- /dev/null
+++ b/src/main/java/com/seibel/lod/core/enums/override/CoreOverrideEnumAssembly.java
@@ -0,0 +1,31 @@
+/*
+ * 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 .
+ */
+
+package com.seibel.lod.core.enums.override;
+
+/**
+ * Assembly classes are used to reference the package they are in.
+ *
+ * @author James Seibel
+ * @version 2022-7-18
+ */
+public class CoreOverrideEnumAssembly
+{
+
+}
diff --git a/src/main/java/com/seibel/lod/core/enums/override/EApiOverridePriority.java b/src/main/java/com/seibel/lod/core/enums/override/EApiOverridePriority.java
new file mode 100644
index 000000000..6e7d79fce
--- /dev/null
+++ b/src/main/java/com/seibel/lod/core/enums/override/EApiOverridePriority.java
@@ -0,0 +1,34 @@
+package com.seibel.lod.core.enums.override;
+
+/**
+ * PRIMARY,
+ * SECONDARY,
+ * CORE,
+ *
+ * @author James Seibel
+ * @version 2022-7-18
+ */
+public enum EApiOverridePriority
+{
+ /**
+ * The default Override priority and the one generally suggested
+ * for developers who want to create an override.
+ * The highest priority.
+ */
+ PRIMARY,
+
+ /**
+ * Overrides with this priority are only used if there isn't
+ * an override with PRIMARY priority.
+ * Could be used to allow creating overrides that other mod developers
+ * could override.
+ */
+ SECONDARY,
+
+ /**
+ * Only Distant Horizons classes should use the CORE priority,
+ * attempting to set an override with CORE priority will result in an error.
+ * This is the lowest priority and will be overridden by all other priorities.
+ */
+ CORE,
+}
diff --git a/src/main/java/com/seibel/lod/core/handlers/dependencyInjection/OverrideInjector.java b/src/main/java/com/seibel/lod/core/handlers/dependencyInjection/OverrideInjector.java
new file mode 100644
index 000000000..ecb05344c
--- /dev/null
+++ b/src/main/java/com/seibel/lod/core/handlers/dependencyInjection/OverrideInjector.java
@@ -0,0 +1,134 @@
+/*
+ * 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 .
+ */
+
+package com.seibel.lod.core.handlers.dependencyInjection;
+
+import com.seibel.lod.core.api.external.items.enums.override.EDhApiOverridePriority;
+import com.seibel.lod.core.api.external.items.interfaces.override.IDhApiOverrideable;
+import com.seibel.lod.core.api.implementation.objects.GenericEnumConverter;
+import com.seibel.lod.core.enums.override.EApiOverridePriority;
+import com.seibel.lod.core.util.StringUtil;
+
+/**
+ * This class takes care of dependency injection for overridable objects.
+ * This is done so other mods can override our methods to improve features down the line.
+ *
+ * @author James Seibel
+ * @version 2022-7-19
+ */
+public class OverrideInjector
+{
+ public static final OverrideInjector INSTANCE = new OverrideInjector();
+
+ private static final DependencyInjector PRIMARY_INJECTOR = new DependencyInjector<>(IDhApiOverrideable.class, false);
+ private static final DependencyInjector SECONDARY_INJECTOR = new DependencyInjector<>(IDhApiOverrideable.class, false);
+ private static final DependencyInjector CORE_INJECTOR = new DependencyInjector<>(IDhApiOverrideable.class, false);
+
+ private static final GenericEnumConverter enumConverter = new GenericEnumConverter<>(EApiOverridePriority.class, EDhApiOverridePriority.class);
+
+
+ /**
+ * See {@link DependencyInjector#bind(Class, IBindable) bind(Class, IBindable)} for full documentation.
+ *
+ * @see DependencyInjector#bind(Class, IBindable)
+ */
+ public void bind(Class extends IDhApiOverrideable> dependencyInterface, IDhApiOverrideable dependencyImplementation) throws IllegalStateException, IllegalArgumentException
+ {
+ if (getCorePriorityEnum(dependencyImplementation) == EApiOverridePriority.PRIMARY)
+ {
+ PRIMARY_INJECTOR.bind(dependencyInterface, dependencyImplementation);
+ }
+ else if (getCorePriorityEnum(dependencyImplementation) == EApiOverridePriority.SECONDARY)
+ {
+ SECONDARY_INJECTOR.bind(dependencyInterface, dependencyImplementation);
+ }
+ else
+ {
+ // not the best way of doing this, but it should work
+ String thisPackageName = this.getClass().getPackage().getName();
+ int secondPackageEndingIndex = StringUtil.nthIndexOf(thisPackageName, ".", 3);
+ String thisPackageBeginningName = thisPackageName.substring(0, secondPackageEndingIndex); // this should be "com.seibel.lod"
+
+ if (dependencyImplementation.getClass().getPackage().getName().startsWith(thisPackageBeginningName))
+ {
+ CORE_INJECTOR.bind(dependencyInterface, dependencyImplementation);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Only Distant Horizons internal objects can use the Override Priority [" + EApiOverridePriority.CORE + "]. Please use [" + EApiOverridePriority.PRIMARY + "] or [" + EApiOverridePriority.SECONDARY + "] instead.");
+ }
+ }
+ }
+
+ /**
+ * Returns the bound dependency with the highest priority.
+ * See {@link DependencyInjector#get(Class, boolean) get(Class, boolean)} for full documentation.
+ *
+ * @see DependencyInjector#get(Class, boolean)
+ */
+ public T get(Class extends IDhApiOverrideable> interfaceClass) throws ClassCastException
+ {
+ T value = PRIMARY_INJECTOR.get(interfaceClass);
+ if (value == null)
+ {
+ value = SECONDARY_INJECTOR.get(interfaceClass);
+ }
+ if (value == null)
+ {
+ value = CORE_INJECTOR.get(interfaceClass);
+ }
+
+ return value;
+ }
+
+ /**
+ * Returns a dependency of type T with the specified priority if one has been bound.
+ * If there is a dependency, but it was bound with a different priority this will return null.
+ *
+ * See {@link DependencyInjector#get(Class, boolean) get(Class, boolean)} for more documentation.
+ *
+ * @see DependencyInjector#get(Class, boolean)
+ */
+ public T get(Class extends IDhApiOverrideable> interfaceClass, EApiOverridePriority overridePriority) throws ClassCastException
+ {
+ T value;
+ if (overridePriority == EApiOverridePriority.PRIMARY)
+ {
+ value = PRIMARY_INJECTOR.get(interfaceClass);
+ }
+ else if (overridePriority == EApiOverridePriority.SECONDARY)
+ {
+ value = SECONDARY_INJECTOR.get(interfaceClass);
+ }
+ else
+ {
+ value = CORE_INJECTOR.get(interfaceClass);
+ }
+
+ return value;
+ }
+
+
+ /** Small helper method so we don't have to use DhApi enums. */
+ private EApiOverridePriority getCorePriorityEnum(IDhApiOverrideable override)
+ {
+ return enumConverter.convertToCoreType(override.getOverrideType());
+ }
+
+}
diff --git a/src/main/java/com/seibel/lod/core/util/StringUtil.java b/src/main/java/com/seibel/lod/core/util/StringUtil.java
new file mode 100644
index 000000000..9f8965ed1
--- /dev/null
+++ b/src/main/java/com/seibel/lod/core/util/StringUtil.java
@@ -0,0 +1,42 @@
+/*
+ * 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 .
+ */
+
+package com.seibel.lod.core.util;
+
+/**
+ * Miscellaneous string helper functions.
+ *
+ * @author James Seibel
+ * @version 2022-7-18
+ */
+public class StringUtil
+{
+ /**
+ * Returns the n-th index of the given string
+ *
+ * Original source: https://stackoverflow.com/questions/3976616/how-to-find-nth-occurrence-of-character-in-a-string
+ */
+ public static int nthIndexOf(String str, String substr, int n)
+ {
+ int pos = str.indexOf(substr);
+ while (--n > 0 && pos != -1)
+ pos = str.indexOf(substr, pos + 1);
+ return pos;
+ }
+}