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 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 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 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; + } +}