feat(D-01/A): config-driven components + tooltip hook (A1, A2, A3)
- ResistanceComponent: resistanceId delegates to SettingsAccessor at runtime, fallback to hardcoded base for backward compat - GaggingComponent: material field delegates to GagMaterial enum from ModConfig, explicit comprehension/range overrides take priority - IItemComponent: add default appendTooltip() method - ComponentHolder: iterate components for tooltip contribution - 6 components implement appendTooltip (lockable, resistance, gagging, shock, gps, choking) - DataDrivenBondageItem: call holder.appendTooltip() in appendHoverText()
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Component: choking effect for data-driven items.
|
||||
@@ -43,4 +50,9 @@ public class ChokingComponent implements IItemComponent {
|
||||
public boolean isNonLethalForMaster() {
|
||||
return nonLethalForMaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.choking").withStyle(ChatFormatting.DARK_PURPLE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,13 @@ package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class ComponentHolder {
|
||||
@@ -58,6 +62,12 @@ public final class ComponentHolder {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
for (IItemComponent c : components.values()) {
|
||||
c.appendTooltip(stack, level, tooltip, flag);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return components.isEmpty();
|
||||
}
|
||||
|
||||
@@ -1,45 +1,94 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.tiedup.remake.core.TiedUpMod;
|
||||
import com.tiedup.remake.util.GagMaterial;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Component: gagging behavior for data-driven items.
|
||||
*
|
||||
* JSON config: {@code "gagging": {"comprehension": 0.2, "range": 10.0}}
|
||||
* <p>Config-driven: {@code "gagging": {"material": "ball"}} delegates to
|
||||
* {@link GagMaterial} for comprehension/range from ModConfig at runtime.</p>
|
||||
*
|
||||
* <p>Override: {@code "gagging": {"comprehension": 0.15, "range": 8.0}} uses
|
||||
* explicit values that take priority over the material lookup.</p>
|
||||
*/
|
||||
public class GaggingComponent implements IItemComponent {
|
||||
|
||||
private final double comprehension;
|
||||
private final double range;
|
||||
private final @Nullable String material;
|
||||
private final double comprehensionOverride;
|
||||
private final double rangeOverride;
|
||||
|
||||
private GaggingComponent(double comprehension, double range) {
|
||||
this.comprehension = comprehension;
|
||||
this.range = range;
|
||||
private GaggingComponent(@Nullable String material, double comprehensionOverride, double rangeOverride) {
|
||||
this.material = material;
|
||||
this.comprehensionOverride = comprehensionOverride;
|
||||
this.rangeOverride = rangeOverride;
|
||||
}
|
||||
|
||||
public static IItemComponent fromJson(JsonObject config) {
|
||||
double comprehension = 0.2;
|
||||
double range = 10.0;
|
||||
String material = null;
|
||||
double comprehension = -1;
|
||||
double range = -1;
|
||||
if (config != null) {
|
||||
if (config.has("material")) {
|
||||
material = config.get("material").getAsString();
|
||||
}
|
||||
if (config.has("comprehension")) {
|
||||
comprehension = config.get("comprehension").getAsDouble();
|
||||
comprehension = Math.max(0.0, Math.min(1.0, config.get("comprehension").getAsDouble()));
|
||||
}
|
||||
if (config.has("range")) {
|
||||
range = config.get("range").getAsDouble();
|
||||
range = Math.max(0.0, config.get("range").getAsDouble());
|
||||
}
|
||||
}
|
||||
comprehension = Math.max(0.0, Math.min(1.0, comprehension));
|
||||
range = Math.max(0.0, range);
|
||||
return new GaggingComponent(comprehension, range);
|
||||
return new GaggingComponent(material, comprehension, range);
|
||||
}
|
||||
|
||||
/** How much of the gagged speech is comprehensible (0.0 = nothing, 1.0 = full). */
|
||||
public double getComprehension() {
|
||||
return comprehension;
|
||||
if (comprehensionOverride >= 0) return comprehensionOverride;
|
||||
GagMaterial gag = getMaterial();
|
||||
if (gag != null) return gag.getComprehension();
|
||||
return 0.2;
|
||||
}
|
||||
|
||||
/** Maximum range in blocks where muffled speech can be heard. */
|
||||
public double getRange() {
|
||||
return range;
|
||||
if (rangeOverride >= 0) return rangeOverride;
|
||||
GagMaterial gag = getMaterial();
|
||||
if (gag != null) return gag.getTalkRange();
|
||||
return 10.0;
|
||||
}
|
||||
|
||||
/** The gag material enum, or null if not configured or invalid. */
|
||||
public @Nullable GagMaterial getMaterial() {
|
||||
if (material == null) return null;
|
||||
try {
|
||||
return GagMaterial.valueOf(material.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
TiedUpMod.LOGGER.warn("[GaggingComponent] Unknown gag material: {}", material);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** The raw material string from JSON, or null. */
|
||||
public @Nullable String getMaterialName() {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
if (material != null) {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.gag_material", material)
|
||||
.withStyle(ChatFormatting.RED));
|
||||
} else {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.gagging").withStyle(ChatFormatting.RED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Component: GPS tracking and safe zone for data-driven items.
|
||||
@@ -42,4 +49,14 @@ public class GpsComponent implements IItemComponent {
|
||||
public boolean isPublicTracking() {
|
||||
return publicTracking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.gps_tracking")
|
||||
.withStyle(ChatFormatting.AQUA));
|
||||
if (safeZoneRadius > 0) {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.gps_zone_radius", safeZoneRadius)
|
||||
.withStyle(ChatFormatting.DARK_AQUA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A reusable behavior module for data-driven bondage items.
|
||||
@@ -16,4 +21,6 @@ public interface IItemComponent {
|
||||
default boolean blocksUnequip(ItemStack stack, LivingEntity entity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
default void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Component: lockable behavior for data-driven items.
|
||||
@@ -41,4 +48,13 @@ public class LockableComponent implements IItemComponent {
|
||||
public int getLockResistance() {
|
||||
return lockResistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.lockable").withStyle(ChatFormatting.GOLD));
|
||||
if (flag.isAdvanced()) {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.lock_resistance", lockResistance)
|
||||
.withStyle(ChatFormatting.DARK_GRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,70 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.tiedup.remake.core.SettingsAccessor;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Component: struggle resistance for data-driven items.
|
||||
*
|
||||
* JSON config: {@code "resistance": {"base": 150}}
|
||||
* <p>Config-driven: {@code "resistance": {"id": "rope"}} delegates to
|
||||
* {@link SettingsAccessor#getBindResistance(String)} at runtime.</p>
|
||||
*
|
||||
* <p>Legacy/override: {@code "resistance": {"base": 150}} uses a hardcoded value.</p>
|
||||
*/
|
||||
public class ResistanceComponent implements IItemComponent {
|
||||
|
||||
private final int baseResistance;
|
||||
private final @Nullable String resistanceId;
|
||||
private final int fallbackBase;
|
||||
|
||||
private ResistanceComponent(int baseResistance) {
|
||||
this.baseResistance = baseResistance;
|
||||
private ResistanceComponent(@Nullable String resistanceId, int fallbackBase) {
|
||||
this.resistanceId = resistanceId;
|
||||
this.fallbackBase = fallbackBase;
|
||||
}
|
||||
|
||||
public static IItemComponent fromJson(JsonObject config) {
|
||||
String id = null;
|
||||
int base = 100;
|
||||
if (config != null && config.has("base")) {
|
||||
base = config.get("base").getAsInt();
|
||||
if (config != null) {
|
||||
if (config.has("id")) {
|
||||
id = config.get("id").getAsString();
|
||||
}
|
||||
if (config.has("base")) {
|
||||
base = config.get("base").getAsInt();
|
||||
}
|
||||
}
|
||||
base = Math.max(0, base);
|
||||
return new ResistanceComponent(base);
|
||||
return new ResistanceComponent(id, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base resistance for this item.
|
||||
* If a {@code resistanceId} is configured, delegates to server config at runtime.
|
||||
* Otherwise returns the hardcoded fallback value.
|
||||
*/
|
||||
public int getBaseResistance() {
|
||||
return baseResistance;
|
||||
if (resistanceId != null) {
|
||||
return SettingsAccessor.getBindResistance(resistanceId);
|
||||
}
|
||||
return fallbackBase;
|
||||
}
|
||||
|
||||
/** The config key used for runtime resistance lookup, or null if hardcoded. */
|
||||
public @Nullable String getResistanceId() {
|
||||
return resistanceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
if (flag.isAdvanced()) {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.resistance", getBaseResistance())
|
||||
.withStyle(ChatFormatting.DARK_GRAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
package com.tiedup.remake.v2.bondage.component;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Component: shock collar behavior for data-driven items.
|
||||
@@ -49,4 +56,16 @@ public class ShockComponent implements IItemComponent {
|
||||
public boolean hasAutoShock() {
|
||||
return autoInterval > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag flag) {
|
||||
if (hasAutoShock()) {
|
||||
float seconds = autoInterval / 20.0f;
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.shock_auto", String.format("%.1f", seconds))
|
||||
.withStyle(ChatFormatting.DARK_RED));
|
||||
} else {
|
||||
tooltip.add(Component.translatable("item.tiedup.tooltip.shock_manual")
|
||||
.withStyle(ChatFormatting.DARK_RED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +246,12 @@ public class DataDrivenBondageItem extends AbstractV2BondageItem {
|
||||
}
|
||||
}
|
||||
|
||||
// Component tooltips
|
||||
ComponentHolder holder = DataDrivenItemRegistry.getComponents(stack);
|
||||
if (holder != null) {
|
||||
holder.appendTooltip(stack, level, tooltip, flag);
|
||||
}
|
||||
|
||||
// Lock status + escape difficulty (from AbstractV2BondageItem)
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user