feature/d01-branch-a-bridge #6
@@ -0,0 +1,95 @@
|
||||
package com.tiedup.remake.v2.bondage;
|
||||
|
||||
import com.tiedup.remake.items.base.ItemBind;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition;
|
||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
|
||||
import java.util.Map;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Static utilities for bind mode operations on any bondage item stack (V1 or V2).
|
||||
*
|
||||
* <p>Bind mode determines whether a bind restrains arms, legs, or both.
|
||||
* The mode is stored in the stack's NBT tag {@code "bindMode"}.</p>
|
||||
*/
|
||||
public final class BindModeHelper {
|
||||
|
||||
private BindModeHelper() {}
|
||||
|
||||
private static final String NBT_BIND_MODE = "bindMode";
|
||||
|
||||
public static final String MODE_FULL = "full";
|
||||
public static final String MODE_ARMS = "arms";
|
||||
public static final String MODE_LEGS = "legs";
|
||||
|
||||
private static final String[] MODE_CYCLE = { MODE_FULL, MODE_ARMS, MODE_LEGS };
|
||||
|
||||
private static final Map<String, String> MODE_TRANSLATION_KEYS = Map.of(
|
||||
MODE_FULL, "tiedup.bindmode.full",
|
||||
MODE_ARMS, "tiedup.bindmode.arms",
|
||||
MODE_LEGS, "tiedup.bindmode.legs"
|
||||
);
|
||||
|
||||
/**
|
||||
* Check if the given stack is a bind item (V2 ARMS-region item or V1 ItemBind).
|
||||
*/
|
||||
public static boolean isBindItem(ItemStack stack) {
|
||||
if (stack.isEmpty()) return false;
|
||||
// V2: check data-driven definition
|
||||
DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
|
||||
if (def != null) {
|
||||
return def.occupiedRegions().contains(BodyRegionV2.ARMS);
|
||||
}
|
||||
// V1 fallback
|
||||
return stack.getItem() instanceof ItemBind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bind mode ID from the stack's NBT.
|
||||
* @return "full", "arms", or "legs" (defaults to "full")
|
||||
*/
|
||||
public static String getBindModeId(ItemStack stack) {
|
||||
if (stack.isEmpty()) return MODE_FULL;
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains(NBT_BIND_MODE)) return MODE_FULL;
|
||||
String value = tag.getString(NBT_BIND_MODE);
|
||||
if (MODE_ARMS.equals(value) || MODE_LEGS.equals(value)) return value;
|
||||
return MODE_FULL;
|
||||
}
|
||||
|
||||
/** True if arms are restrained (mode is "arms" or "full"). */
|
||||
public static boolean hasArmsBound(ItemStack stack) {
|
||||
String mode = getBindModeId(stack);
|
||||
return MODE_ARMS.equals(mode) || MODE_FULL.equals(mode);
|
||||
}
|
||||
|
||||
/** True if legs are restrained (mode is "legs" or "full"). */
|
||||
public static boolean hasLegsBound(ItemStack stack) {
|
||||
String mode = getBindModeId(stack);
|
||||
return MODE_LEGS.equals(mode) || MODE_FULL.equals(mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle bind mode: full → arms → legs → full.
|
||||
* @return the new mode ID
|
||||
*/
|
||||
public static String cycleBindModeId(ItemStack stack) {
|
||||
String current = getBindModeId(stack);
|
||||
String next = MODE_FULL;
|
||||
for (int i = 0; i < MODE_CYCLE.length; i++) {
|
||||
if (MODE_CYCLE[i].equals(current)) {
|
||||
next = MODE_CYCLE[(i + 1) % MODE_CYCLE.length];
|
||||
break;
|
||||
}
|
||||
}
|
||||
stack.getOrCreateTag().putString(NBT_BIND_MODE, next);
|
||||
return next;
|
||||
}
|
||||
|
||||
/** Get the translation key for the current bind mode. */
|
||||
public static String getBindModeTranslationKey(ItemStack stack) {
|
||||
return MODE_TRANSLATION_KEYS.getOrDefault(getBindModeId(stack), "tiedup.bindmode.full");
|
||||
}
|
||||
}
|
||||
371
src/main/java/com/tiedup/remake/v2/bondage/CollarHelper.java
Normal file
371
src/main/java/com/tiedup/remake/v2/bondage/CollarHelper.java
Normal file
@@ -0,0 +1,371 @@
|
||||
package com.tiedup.remake.v2.bondage;
|
||||
|
||||
import com.tiedup.remake.items.ItemChokeCollar;
|
||||
import com.tiedup.remake.items.ItemGpsCollar;
|
||||
import com.tiedup.remake.items.ItemShockCollar;
|
||||
import com.tiedup.remake.items.ItemShockCollarAuto;
|
||||
import com.tiedup.remake.items.base.ItemCollar;
|
||||
import com.tiedup.remake.v2.bondage.component.ChokingComponent;
|
||||
import com.tiedup.remake.v2.bondage.component.ComponentType;
|
||||
import com.tiedup.remake.v2.bondage.component.GpsComponent;
|
||||
import com.tiedup.remake.v2.bondage.component.OwnershipComponent;
|
||||
import com.tiedup.remake.v2.bondage.component.ShockComponent;
|
||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Static utility for collar operations bridging V1 (ItemCollar subclasses)
|
||||
* and V2 (data-driven items with OwnershipComponent).
|
||||
*/
|
||||
public final class CollarHelper {
|
||||
|
||||
private CollarHelper() {}
|
||||
|
||||
// ===== DETECTION =====
|
||||
|
||||
// True if the stack is any kind of collar (V2 ownership component or V1 ItemCollar)
|
||||
public static boolean isCollar(ItemStack stack) {
|
||||
if (stack.isEmpty()) return false;
|
||||
if (DataDrivenBondageItem.getComponent(stack, ComponentType.OWNERSHIP, OwnershipComponent.class) != null) {
|
||||
return true;
|
||||
}
|
||||
return stack.getItem() instanceof ItemCollar;
|
||||
}
|
||||
|
||||
// ===== OWNERSHIP (NBT: "owners") =====
|
||||
|
||||
// Returns all owner UUIDs stored in the collar's "owners" ListTag
|
||||
public static List<UUID> getOwners(ItemStack stack) {
|
||||
return getListUUIDs(stack, "owners");
|
||||
}
|
||||
|
||||
// True if the given UUID is in the owners list
|
||||
public static boolean isOwner(ItemStack stack, UUID uuid) {
|
||||
return hasUUIDInList(stack, "owners", uuid);
|
||||
}
|
||||
|
||||
// True if the given player is an owner
|
||||
public static boolean isOwner(ItemStack stack, Player player) {
|
||||
return isOwner(stack, player.getUUID());
|
||||
}
|
||||
|
||||
// True if the collar has at least one owner
|
||||
public static boolean hasOwner(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains("owners", Tag.TAG_LIST)) return false;
|
||||
return !tag.getList("owners", Tag.TAG_COMPOUND).isEmpty();
|
||||
}
|
||||
|
||||
// Adds an owner entry {uuid, name} to the "owners" ListTag
|
||||
public static void addOwner(ItemStack stack, UUID uuid, String name) {
|
||||
addToList(stack, "owners", uuid, name);
|
||||
}
|
||||
|
||||
// Convenience: add a player as owner
|
||||
public static void addOwner(ItemStack stack, Player player) {
|
||||
addOwner(stack, player.getUUID(), player.getGameProfile().getName());
|
||||
}
|
||||
|
||||
// Removes an owner by UUID
|
||||
public static void removeOwner(ItemStack stack, UUID uuid) {
|
||||
removeFromList(stack, "owners", uuid);
|
||||
}
|
||||
|
||||
// ===== BLACKLIST (NBT: "blacklist") =====
|
||||
|
||||
public static List<UUID> getBlacklist(ItemStack stack) {
|
||||
return getListUUIDs(stack, "blacklist");
|
||||
}
|
||||
|
||||
public static boolean isBlacklisted(ItemStack stack, UUID uuid) {
|
||||
return hasUUIDInList(stack, "blacklist", uuid);
|
||||
}
|
||||
|
||||
public static void addToBlacklist(ItemStack stack, UUID uuid, String name) {
|
||||
addToList(stack, "blacklist", uuid, name);
|
||||
}
|
||||
|
||||
public static void removeFromBlacklist(ItemStack stack, UUID uuid) {
|
||||
removeFromList(stack, "blacklist", uuid);
|
||||
}
|
||||
|
||||
// ===== WHITELIST (NBT: "whitelist") =====
|
||||
|
||||
public static List<UUID> getWhitelist(ItemStack stack) {
|
||||
return getListUUIDs(stack, "whitelist");
|
||||
}
|
||||
|
||||
public static boolean isWhitelisted(ItemStack stack, UUID uuid) {
|
||||
return hasUUIDInList(stack, "whitelist", uuid);
|
||||
}
|
||||
|
||||
public static void addToWhitelist(ItemStack stack, UUID uuid, String name) {
|
||||
addToList(stack, "whitelist", uuid, name);
|
||||
}
|
||||
|
||||
public static void removeFromWhitelist(ItemStack stack, UUID uuid) {
|
||||
removeFromList(stack, "whitelist", uuid);
|
||||
}
|
||||
|
||||
// ===== LIST INTERNALS =====
|
||||
|
||||
private static List<UUID> getListUUIDs(ItemStack stack, String listKey) {
|
||||
List<UUID> result = new ArrayList<>();
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains(listKey, Tag.TAG_LIST)) return result;
|
||||
ListTag list = tag.getList(listKey, Tag.TAG_COMPOUND);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CompoundTag entry = list.getCompound(i);
|
||||
if (entry.contains("uuid")) {
|
||||
try {
|
||||
result.add(UUID.fromString(entry.getString("uuid")));
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// Malformed UUID in NBT, skip
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean hasUUIDInList(ItemStack stack, String listKey, UUID uuid) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains(listKey, Tag.TAG_LIST)) return false;
|
||||
String uuidStr = uuid.toString();
|
||||
ListTag list = tag.getList(listKey, Tag.TAG_COMPOUND);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (uuidStr.equals(list.getCompound(i).getString("uuid"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void addToList(ItemStack stack, String listKey, UUID uuid, String name) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
ListTag list = tag.contains(listKey, Tag.TAG_LIST)
|
||||
? tag.getList(listKey, Tag.TAG_COMPOUND)
|
||||
: new ListTag();
|
||||
// Prevent duplicates
|
||||
String uuidStr = uuid.toString();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (uuidStr.equals(list.getCompound(i).getString("uuid"))) return;
|
||||
}
|
||||
CompoundTag entry = new CompoundTag();
|
||||
entry.putString("uuid", uuidStr);
|
||||
entry.putString("name", name);
|
||||
list.add(entry);
|
||||
tag.put(listKey, list);
|
||||
}
|
||||
|
||||
private static void removeFromList(ItemStack stack, String listKey, UUID uuid) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains(listKey, Tag.TAG_LIST)) return;
|
||||
String uuidStr = uuid.toString();
|
||||
ListTag list = tag.getList(listKey, Tag.TAG_COMPOUND);
|
||||
list.removeIf(element ->
|
||||
uuidStr.equals(((CompoundTag) element).getString("uuid"))
|
||||
);
|
||||
}
|
||||
|
||||
// ===== FEATURES =====
|
||||
|
||||
@Nullable
|
||||
public static String getNickname(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains("nickname")) return null;
|
||||
return tag.getString("nickname");
|
||||
}
|
||||
|
||||
public static void setNickname(ItemStack stack, String nickname) {
|
||||
stack.getOrCreateTag().putString("nickname", nickname);
|
||||
}
|
||||
|
||||
public static boolean hasNickname(ItemStack stack) {
|
||||
return stack.hasTag() && stack.getTag().contains("nickname");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static UUID getCellId(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains("cellId")) return null;
|
||||
try {
|
||||
return UUID.fromString(tag.getString("cellId"));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setCellId(ItemStack stack, UUID cellId) {
|
||||
stack.getOrCreateTag().putString("cellId", cellId.toString());
|
||||
}
|
||||
|
||||
public static boolean hasCellAssigned(ItemStack stack) {
|
||||
return getCellId(stack) != null;
|
||||
}
|
||||
|
||||
public static boolean isKidnappingModeEnabled(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.getBoolean("kidnappingMode");
|
||||
}
|
||||
|
||||
public static void setKidnappingModeEnabled(ItemStack stack, boolean enabled) {
|
||||
stack.getOrCreateTag().putBoolean("kidnappingMode", enabled);
|
||||
}
|
||||
|
||||
// Kidnapping mode is ready when enabled AND a cell is assigned
|
||||
public static boolean isKidnappingModeReady(ItemStack stack) {
|
||||
return isKidnappingModeEnabled(stack) && hasCellAssigned(stack);
|
||||
}
|
||||
|
||||
public static boolean shouldTieToPole(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.getBoolean("tieToPole");
|
||||
}
|
||||
|
||||
public static void setShouldTieToPole(ItemStack stack, boolean value) {
|
||||
stack.getOrCreateTag().putBoolean("tieToPole", value);
|
||||
}
|
||||
|
||||
// Default true when tag is absent or key is missing
|
||||
public static boolean shouldWarnMasters(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains("warnMasters")) return true;
|
||||
return tag.getBoolean("warnMasters");
|
||||
}
|
||||
|
||||
public static void setShouldWarnMasters(ItemStack stack, boolean value) {
|
||||
stack.getOrCreateTag().putBoolean("warnMasters", value);
|
||||
}
|
||||
|
||||
public static boolean isBondageServiceEnabled(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.getBoolean("bondageservice");
|
||||
}
|
||||
|
||||
public static void setBondageServiceEnabled(ItemStack stack, boolean enabled) {
|
||||
stack.getOrCreateTag().putBoolean("bondageservice", enabled);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getServiceSentence(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains("servicesentence")) return null;
|
||||
return tag.getString("servicesentence");
|
||||
}
|
||||
|
||||
public static void setServiceSentence(ItemStack stack, String sentence) {
|
||||
stack.getOrCreateTag().putString("servicesentence", sentence);
|
||||
}
|
||||
|
||||
// ===== SHOCK =====
|
||||
|
||||
// True if the collar can shock (V2 ShockComponent or V1 ItemShockCollar)
|
||||
public static boolean canShock(ItemStack stack) {
|
||||
if (stack.isEmpty()) return false;
|
||||
if (DataDrivenBondageItem.getComponent(stack, ComponentType.SHOCK, ShockComponent.class) != null) {
|
||||
return true;
|
||||
}
|
||||
return stack.getItem() instanceof ItemShockCollar;
|
||||
}
|
||||
|
||||
public static boolean isPublicShock(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.getBoolean("public_mode");
|
||||
}
|
||||
|
||||
public static void setPublicShock(ItemStack stack, boolean publicMode) {
|
||||
stack.getOrCreateTag().putBoolean("public_mode", publicMode);
|
||||
}
|
||||
|
||||
// V2: from ShockComponent auto interval, V1: from ItemShockCollarAuto field, else 0
|
||||
public static int getShockInterval(ItemStack stack) {
|
||||
ShockComponent comp = DataDrivenBondageItem.getComponent(
|
||||
stack, ComponentType.SHOCK, ShockComponent.class
|
||||
);
|
||||
if (comp != null) return comp.getAutoInterval();
|
||||
if (stack.getItem() instanceof ItemShockCollarAuto auto) {
|
||||
return auto.getInterval();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ===== GPS =====
|
||||
|
||||
// True if the collar has GPS capabilities
|
||||
public static boolean hasGPS(ItemStack stack) {
|
||||
if (stack.isEmpty()) return false;
|
||||
if (DataDrivenBondageItem.getComponent(stack, ComponentType.GPS, GpsComponent.class) != null) {
|
||||
return true;
|
||||
}
|
||||
return stack.getItem() instanceof ItemGpsCollar;
|
||||
}
|
||||
|
||||
public static boolean hasPublicTracking(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.getBoolean("publicTracking");
|
||||
}
|
||||
|
||||
public static void setPublicTracking(ItemStack stack, boolean publicTracking) {
|
||||
stack.getOrCreateTag().putBoolean("publicTracking", publicTracking);
|
||||
}
|
||||
|
||||
// GPS active defaults to true when absent
|
||||
public static boolean isActive(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null || !tag.contains("gpsActive")) return true;
|
||||
return tag.getBoolean("gpsActive");
|
||||
}
|
||||
|
||||
public static void setActive(ItemStack stack, boolean active) {
|
||||
stack.getOrCreateTag().putBoolean("gpsActive", active);
|
||||
}
|
||||
|
||||
// ===== CHOKE =====
|
||||
|
||||
// True if the collar is a choke collar
|
||||
public static boolean isChokeCollar(ItemStack stack) {
|
||||
if (stack.isEmpty()) return false;
|
||||
if (DataDrivenBondageItem.getComponent(stack, ComponentType.CHOKING, ChokingComponent.class) != null) {
|
||||
return true;
|
||||
}
|
||||
return stack.getItem() instanceof ItemChokeCollar;
|
||||
}
|
||||
|
||||
public static boolean isChoking(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.getBoolean("choking");
|
||||
}
|
||||
|
||||
public static void setChoking(ItemStack stack, boolean choking) {
|
||||
stack.getOrCreateTag().putBoolean("choking", choking);
|
||||
}
|
||||
|
||||
public static boolean isPetPlayMode(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
return tag != null && tag.getBoolean("petPlayMode");
|
||||
}
|
||||
|
||||
public static void setPetPlayMode(ItemStack stack, boolean petPlay) {
|
||||
stack.getOrCreateTag().putBoolean("petPlayMode", petPlay);
|
||||
}
|
||||
|
||||
// ===== ALERT SUPPRESSION =====
|
||||
|
||||
// Executes the action with collar removal alerts suppressed
|
||||
public static void runWithSuppressedAlert(Runnable action) {
|
||||
ItemCollar.runWithSuppressedAlert(action);
|
||||
}
|
||||
|
||||
// True if removal alerts are currently suppressed (ThreadLocal state)
|
||||
public static boolean isRemovalAlertSuppressed() {
|
||||
return ItemCollar.isRemovalAlertSuppressed();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.tiedup.remake.v2.bondage;
|
||||
|
||||
import com.tiedup.remake.items.base.ItemBind;
|
||||
import com.tiedup.remake.items.base.PoseType;
|
||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition;
|
||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Resolves the {@link PoseType} for any bondage item stack (V1 or V2).
|
||||
*
|
||||
* <p>V2 items read from the data-driven definition's {@code pose_type} field.
|
||||
* V1 items fall back to {@code ItemBind.getPoseType()}.</p>
|
||||
*/
|
||||
public final class PoseTypeHelper {
|
||||
|
||||
private PoseTypeHelper() {}
|
||||
|
||||
public static PoseType getPoseType(ItemStack stack) {
|
||||
// V2: read from data-driven definition
|
||||
DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
|
||||
if (def != null && def.poseType() != null) {
|
||||
try {
|
||||
return PoseType.valueOf(def.poseType().toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return PoseType.STANDARD;
|
||||
}
|
||||
}
|
||||
// V1 fallback
|
||||
if (stack.getItem() instanceof ItemBind bind) {
|
||||
return bind.getPoseType();
|
||||
}
|
||||
return PoseType.STANDARD;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,8 @@ public enum ComponentType {
|
||||
SHOCK("shock", ShockComponent::fromJson),
|
||||
GPS("gps", GpsComponent::fromJson),
|
||||
CHOKING("choking", ChokingComponent::fromJson),
|
||||
ADJUSTABLE("adjustable", AdjustableComponent::fromJson);
|
||||
ADJUSTABLE("adjustable", AdjustableComponent::fromJson),
|
||||
OWNERSHIP("ownership", OwnershipComponent::fromJson);
|
||||
|
||||
private final String jsonKey;
|
||||
private final Function<JsonObject, IItemComponent> factory;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Component: collar ownership behavior for data-driven items.
|
||||
*
|
||||
* <p>Marks an item as a collar with ownership capabilities.
|
||||
* Lifecycle hooks handle CollarRegistry registration/unregistration.</p>
|
||||
*
|
||||
* <p>JSON config: {@code "ownership": {}}</p>
|
||||
*/
|
||||
public class OwnershipComponent implements IItemComponent {
|
||||
|
||||
private OwnershipComponent() {}
|
||||
|
||||
public static IItemComponent fromJson(JsonObject config) {
|
||||
return new OwnershipComponent();
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,9 @@ public record DataDrivenItemDefinition(
|
||||
/** Body regions this item blocks. Defaults to occupiedRegions if not specified. */
|
||||
Set<BodyRegionV2> blockedRegions,
|
||||
|
||||
/** Optional pose type identifier (e.g., "STANDARD", "STRAITJACKET", "DOG"). */
|
||||
@Nullable String poseType,
|
||||
|
||||
/** Pose priority for conflict resolution. Higher wins. */
|
||||
int posePriority,
|
||||
|
||||
|
||||
@@ -188,6 +188,9 @@ public final class DataDrivenItemParser {
|
||||
blockedRegions = occupiedRegions;
|
||||
}
|
||||
|
||||
// Optional: pose_type (e.g., "STANDARD", "STRAITJACKET", "DOG")
|
||||
String poseType = getStringOrNull(root, "pose_type");
|
||||
|
||||
// Optional: pose_priority (default 0)
|
||||
int posePriority = getIntOrDefault(root, "pose_priority", 0);
|
||||
|
||||
@@ -328,6 +331,7 @@ public final class DataDrivenItemParser {
|
||||
animationSource,
|
||||
occupiedRegions,
|
||||
blockedRegions,
|
||||
poseType,
|
||||
posePriority,
|
||||
escapeDifficulty,
|
||||
lockable,
|
||||
|
||||
Reference in New Issue
Block a user