diff --git a/mccore/src/main/java/minecrafttransportsimulator/entities/instances/PartInteractable.java b/mccore/src/main/java/minecrafttransportsimulator/entities/instances/PartInteractable.java index 2c803f3f1..c98e1fe19 100644 --- a/mccore/src/main/java/minecrafttransportsimulator/entities/instances/PartInteractable.java +++ b/mccore/src/main/java/minecrafttransportsimulator/entities/instances/PartInteractable.java @@ -20,6 +20,9 @@ import minecrafttransportsimulator.systems.LanguageSystem; import minecrafttransportsimulator.systems.LanguageSystem.LanguageEntry; +import java.util.HashMap; +import java.util.Map; + public final class PartInteractable extends APart { public final AEntityCrafter crafter; public final EntityInventoryContainer inventory; @@ -31,6 +34,7 @@ public final class PartInteractable extends APart { public static final String JERRYCAN_FLUID_NAME = "jerrycanFluid"; public static final String BATTERY_CHARGED_NAME = "batteryCharged"; + public static final Map CUSTOM_INTERACTION_HANDLERS = new HashMap<>(); public PartInteractable(AEntityF_Multipart entityOn, IWrapperPlayer placingPlayer, JSONPartDefinition placementDefinition, ItemPartInteractable item, IWrapperNBT data) { super(entityOn, placingPlayer, placementDefinition, item, data); @@ -92,6 +96,9 @@ public PartInteractable(AEntityF_Multipart entityOn, IWrapperPlayer placingPl } //No break statement here, fall-down to default to null things. } + case CUSTOM: { + CUSTOM_INTERACTION_HANDLERS.get(definition.interactable.customInteractionHandler).onInit(this, entityOn, placingPlayer, placementDefinition, item, data); + } default: { this.crafter = null; this.inventory = null; @@ -127,6 +134,10 @@ public boolean interact(IWrapperPlayer player) { player.getHeldStack().interactWith(tank, player); break; } + case CUSTOM: { + CUSTOM_INTERACTION_HANDLERS.get(definition.interactable.customInteractionHandler).onInteract(this, player); + break; + } } } else { player.sendPacket(new PacketPlayerChatMessage(player, LanguageSystem.INTERACT_VEHICLE_LOCKED)); @@ -160,6 +171,10 @@ public void remove() { if (tank != null) { tank.remove(); } + + if (definition.interactable.interactionType == InteractableComponentType.CUSTOM) { + CUSTOM_INTERACTION_HANDLERS.get(definition.interactable.customInteractionHandler).onRemove(this); + } } @Override @@ -244,6 +259,10 @@ public void update() { player.sendPacket(new PacketPlayerChatMessage(player, linkedMessage)); } } + + if (definition.interactable.interactionType == InteractableComponentType.CUSTOM) { + CUSTOM_INTERACTION_HANDLERS.get(definition.interactable.customInteractionHandler).onUpdate(this); + } } } @@ -378,6 +397,27 @@ public IWrapperNBT save(IWrapperNBT data) { } else if (definition.interactable.interactionType == InteractableComponentType.BATTERY) { data.setBoolean(BATTERY_CHARGED_NAME, batteryCharged); } + + if (definition.interactable.interactionType == InteractableComponentType.CUSTOM) + CUSTOM_INTERACTION_HANDLERS.get(definition.interactable.customInteractionHandler).save(this, data); return data; } + + public static void registerCustomInteractionHandler(String name, CustomInteractionHandler handler) { + if (CUSTOM_INTERACTION_HANDLERS.containsKey(name)) + throw new RuntimeException("A custom interaction handler with name " + name + " has already been registered!"); + CUSTOM_INTERACTION_HANDLERS.put(name, handler); + } + + public interface CustomInteractionHandler { + void onInit(PartInteractable interactable, AEntityF_Multipart entityOn, IWrapperPlayer placingPlayer, JSONPartDefinition placementDefinition, ItemPartInteractable item, IWrapperNBT data); + + void onInteract(PartInteractable interactable, IWrapperPlayer player); + + void onUpdate(PartInteractable interactable); + + void onRemove(PartInteractable interactable); + + void save(PartInteractable interactable, IWrapperNBT data); + } } diff --git a/mccore/src/main/java/minecrafttransportsimulator/jsondefs/JSONPart.java b/mccore/src/main/java/minecrafttransportsimulator/jsondefs/JSONPart.java index 8869d93fa..1258eece0 100644 --- a/mccore/src/main/java/minecrafttransportsimulator/jsondefs/JSONPart.java +++ b/mccore/src/main/java/minecrafttransportsimulator/jsondefs/JSONPart.java @@ -587,6 +587,10 @@ public static class JSONPartInteractable { @JSONDescription("A optional crafting definition for this interactable. Requires an interactable type of crafting_bench to do anything.") public JSONCraftingBench crafting; + @JSONDescription("The name of the code-defined interaction handler to utilize. Requires an interactable type of custom to do anything.") + @JSONRequired(dependentField = "interactionType", dependentValues = {"custom"}) + public String customInteractionHandler; + @Deprecated public String inventoryTexture; @Deprecated @@ -613,7 +617,9 @@ public enum InteractableComponentType { @JSONDescription("Works as a battery, allowing a charge to be stored inside and then used to charge electric vehicles without a charger.") BATTERY, @JSONDescription("Works as a MTS crafting bench when clicked. This requires supplemental parameters.") - CRAFTING_BENCH + CRAFTING_BENCH, + @JSONDescription("Works based on the code-defined custom interaction handler. Useful for mod integration!") + CUSTOM } public enum CrafterComponentType {