fix/swarm-review-p0-p1-p2 #15
@@ -104,6 +104,7 @@ minecraft {
|
|||||||
|
|
||||||
// Mixin config arg
|
// Mixin config arg
|
||||||
args '-mixin.config=tiedup.mixins.json'
|
args '-mixin.config=tiedup.mixins.json'
|
||||||
|
args '-mixin.config=tiedup-compat.mixins.json'
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
@@ -116,6 +117,7 @@ minecraft {
|
|||||||
|
|
||||||
// Mixin config arg
|
// Mixin config arg
|
||||||
args '-mixin.config=tiedup.mixins.json'
|
args '-mixin.config=tiedup.mixins.json'
|
||||||
|
args '-mixin.config=tiedup-compat.mixins.json'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional client instances for multiplayer testing
|
// Additional client instances for multiplayer testing
|
||||||
@@ -155,6 +157,7 @@ sourceSets.main.resources { srcDir 'src/generated/resources' }
|
|||||||
mixin {
|
mixin {
|
||||||
add sourceSets.main, 'tiedup.refmap.json'
|
add sourceSets.main, 'tiedup.refmap.json'
|
||||||
config 'tiedup.mixins.json'
|
config 'tiedup.mixins.json'
|
||||||
|
config 'tiedup-compat.mixins.json'
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -263,7 +266,7 @@ tasks.named('jar', Jar).configure {
|
|||||||
'Implementation-Version' : project.jar.archiveVersion,
|
'Implementation-Version' : project.jar.archiveVersion,
|
||||||
'Implementation-Vendor' : mod_authors,
|
'Implementation-Vendor' : mod_authors,
|
||||||
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||||
'MixinConfigs' : 'tiedup.mixins.json'
|
'MixinConfigs' : 'tiedup.mixins.json,tiedup-compat.mixins.json'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ public class BlockKidnapBomb
|
|||||||
beTag.contains("collar")
|
beTag.contains("collar")
|
||||||
) {
|
) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Loaded:").withStyle(
|
Component.translatable("block.tiedup.kidnap_bomb.loaded").withStyle(
|
||||||
ChatFormatting.YELLOW
|
ChatFormatting.YELLOW
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -282,12 +282,12 @@ public class BlockKidnapBomb
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Empty").withStyle(ChatFormatting.GREEN)
|
Component.translatable("block.tiedup.kidnap_bomb.empty").withStyle(ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Empty").withStyle(ChatFormatting.GREEN)
|
Component.translatable("block.tiedup.kidnap_bomb.empty").withStyle(ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ public class BlockRopeTrap extends Block implements EntityBlock, ICanBeLoaded {
|
|||||||
// Check if armed
|
// Check if armed
|
||||||
if (beTag.contains("bind")) {
|
if (beTag.contains("bind")) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Armed").withStyle(
|
Component.translatable("block.tiedup.trap.armed").withStyle(
|
||||||
ChatFormatting.DARK_RED
|
ChatFormatting.DARK_RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -366,14 +366,14 @@ public class BlockRopeTrap extends Block implements EntityBlock, ICanBeLoaded {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Disarmed").withStyle(
|
Component.translatable("block.tiedup.trap.disarmed").withStyle(
|
||||||
ChatFormatting.GREEN
|
ChatFormatting.GREEN
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Disarmed").withStyle(ChatFormatting.GREEN)
|
Component.translatable("block.tiedup.trap.disarmed").withStyle(ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ public class BlockTrappedChest extends ChestBlock implements ICanBeLoaded {
|
|||||||
beTag.contains("collar")
|
beTag.contains("collar")
|
||||||
) {
|
) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Armed").withStyle(
|
Component.translatable("block.tiedup.trap.armed").withStyle(
|
||||||
ChatFormatting.DARK_RED
|
ChatFormatting.DARK_RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -231,14 +231,14 @@ public class BlockTrappedChest extends ChestBlock implements ICanBeLoaded {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Disarmed").withStyle(
|
Component.translatable("block.tiedup.trap.disarmed").withStyle(
|
||||||
ChatFormatting.GREEN
|
ChatFormatting.GREEN
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Disarmed").withStyle(ChatFormatting.GREEN)
|
Component.translatable("block.tiedup.trap.disarmed").withStyle(ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,9 +382,8 @@ public class BountyManager extends SavedData {
|
|||||||
server
|
server
|
||||||
.getPlayerList()
|
.getPlayerList()
|
||||||
.broadcastSystemMessage(
|
.broadcastSystemMessage(
|
||||||
Component.literal("[Bounty] " + message).withStyle(
|
Component.translatable("msg.tiedup.bounty.broadcast", message)
|
||||||
ChatFormatting.GOLD
|
.withStyle(ChatFormatting.GOLD),
|
||||||
),
|
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,10 +250,8 @@ public final class CampLifecycleManager {
|
|||||||
|
|
||||||
// Notify prisoner
|
// Notify prisoner
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal("Your captor has died. You are FREE!").withStyle(
|
Component.translatable("msg.tiedup.camp.captor_died")
|
||||||
ChatFormatting.GREEN,
|
.withStyle(ChatFormatting.GREEN, ChatFormatting.BOLD)
|
||||||
ChatFormatting.BOLD
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Grant grace period (5 minutes = 6000 ticks)
|
// Grant grace period (5 minutes = 6000 ticks)
|
||||||
@@ -261,9 +259,8 @@ public final class CampLifecycleManager {
|
|||||||
manager.release(prisoner.getUUID(), level.getGameTime(), 6000);
|
manager.release(prisoner.getUUID(), level.getGameTime(), 6000);
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable("msg.tiedup.camp.grace_period")
|
||||||
"You have 5 minutes of protection from kidnappers."
|
.withStyle(ChatFormatting.AQUA)
|
||||||
).withStyle(ChatFormatting.AQUA)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
TiedUpMod.LOGGER.info(
|
TiedUpMod.LOGGER.info(
|
||||||
|
|||||||
@@ -7,16 +7,12 @@ import com.tiedup.remake.client.animation.PendingAnimationManager;
|
|||||||
import com.tiedup.remake.client.animation.context.AnimationContext;
|
import com.tiedup.remake.client.animation.context.AnimationContext;
|
||||||
import com.tiedup.remake.client.animation.context.AnimationContextResolver;
|
import com.tiedup.remake.client.animation.context.AnimationContextResolver;
|
||||||
import com.tiedup.remake.client.animation.context.RegionBoneMapper;
|
import com.tiedup.remake.client.animation.context.RegionBoneMapper;
|
||||||
import com.tiedup.remake.client.animation.util.AnimationIdBuilder;
|
|
||||||
import com.tiedup.remake.client.events.CellHighlightHandler;
|
import com.tiedup.remake.client.events.CellHighlightHandler;
|
||||||
import com.tiedup.remake.client.events.LeashProxyClientHandler;
|
import com.tiedup.remake.client.events.LeashProxyClientHandler;
|
||||||
import com.tiedup.remake.client.gltf.GltfAnimationApplier;
|
import com.tiedup.remake.client.gltf.GltfAnimationApplier;
|
||||||
import com.tiedup.remake.client.state.ClothesClientCache;
|
import com.tiedup.remake.client.state.ClothesClientCache;
|
||||||
import com.tiedup.remake.client.state.MovementStyleClientState;
|
import com.tiedup.remake.client.state.MovementStyleClientState;
|
||||||
import com.tiedup.remake.client.state.PetBedClientState;
|
import com.tiedup.remake.client.state.PetBedClientState;
|
||||||
import com.tiedup.remake.items.base.PoseType;
|
|
||||||
import com.tiedup.remake.v2.bondage.BindModeHelper;
|
|
||||||
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
|
|
||||||
import com.tiedup.remake.util.HumanChairHelper;
|
import com.tiedup.remake.util.HumanChairHelper;
|
||||||
import com.tiedup.remake.state.PlayerBindState;
|
import com.tiedup.remake.state.PlayerBindState;
|
||||||
import com.tiedup.remake.v2.BodyRegionV2;
|
import com.tiedup.remake.v2.BodyRegionV2;
|
||||||
@@ -205,30 +201,11 @@ public class AnimationTickHandler {
|
|||||||
context,
|
context,
|
||||||
allOwnedParts
|
allOwnedParts
|
||||||
);
|
);
|
||||||
// Clear V1 tracking so transition back works
|
// Clear legacy tracking so transition back works
|
||||||
AnimationStateRegistry.getLastAnimId().remove(uuid);
|
AnimationStateRegistry.getLastAnimId().remove(uuid);
|
||||||
} else {
|
|
||||||
// V1 fallback
|
|
||||||
if (GltfAnimationApplier.hasActiveState(player)) {
|
|
||||||
GltfAnimationApplier.clearV2Animation(player);
|
|
||||||
}
|
|
||||||
String animId = buildAnimationId(player, state);
|
|
||||||
String lastId = AnimationStateRegistry.getLastAnimId().get(
|
|
||||||
uuid
|
|
||||||
);
|
|
||||||
if (!animId.equals(lastId)) {
|
|
||||||
boolean success = BondageAnimationManager.playAnimation(
|
|
||||||
player,
|
|
||||||
animId
|
|
||||||
);
|
|
||||||
if (success) {
|
|
||||||
AnimationStateRegistry.getLastAnimId().put(
|
|
||||||
uuid,
|
|
||||||
animId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// No V2 items with GLB models — nothing to animate.
|
||||||
|
// Items without data-driven GLB definitions are not animated.
|
||||||
} else if (wasTied) {
|
} else if (wasTied) {
|
||||||
// Was tied, now free - stop all animations
|
// Was tied, now free - stop all animations
|
||||||
if (GltfAnimationApplier.hasActiveState(player)) {
|
if (GltfAnimationApplier.hasActiveState(player)) {
|
||||||
@@ -242,53 +219,6 @@ public class AnimationTickHandler {
|
|||||||
AnimationStateRegistry.getLastTiedState().put(uuid, isTied);
|
AnimationStateRegistry.getLastTiedState().put(uuid, isTied);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build animation ID from player's current state (V1 path).
|
|
||||||
*/
|
|
||||||
private static String buildAnimationId(
|
|
||||||
Player player,
|
|
||||||
PlayerBindState state
|
|
||||||
) {
|
|
||||||
ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
|
|
||||||
PoseType poseType = PoseTypeHelper.getPoseType(bind);
|
|
||||||
|
|
||||||
// Human chair mode: override DOG pose to HUMAN_CHAIR (straight limbs)
|
|
||||||
poseType = HumanChairHelper.resolveEffectivePose(poseType, bind);
|
|
||||||
|
|
||||||
// Derive bound state from V2 regions (works client-side, synced via capability)
|
|
||||||
boolean armsBound = V2EquipmentHelper.isRegionOccupied(
|
|
||||||
player,
|
|
||||||
BodyRegionV2.ARMS
|
|
||||||
);
|
|
||||||
boolean legsBound = V2EquipmentHelper.isRegionOccupied(
|
|
||||||
player,
|
|
||||||
BodyRegionV2.LEGS
|
|
||||||
);
|
|
||||||
|
|
||||||
// V1 fallback: if no V2 regions are set but player is tied, derive from bind mode NBT
|
|
||||||
if (!armsBound && !legsBound && BindModeHelper.isBindItem(bind)) {
|
|
||||||
armsBound = BindModeHelper.hasArmsBound(bind);
|
|
||||||
legsBound = BindModeHelper.hasLegsBound(bind);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isStruggling = state.isStruggling();
|
|
||||||
boolean isSneaking = player.isCrouching();
|
|
||||||
boolean isMoving =
|
|
||||||
player.getDeltaMovement().horizontalDistanceSqr() > 1e-6;
|
|
||||||
|
|
||||||
// Build animation ID with sneak and movement support
|
|
||||||
return AnimationIdBuilder.build(
|
|
||||||
poseType,
|
|
||||||
armsBound,
|
|
||||||
legsBound,
|
|
||||||
null,
|
|
||||||
isStruggling,
|
|
||||||
true,
|
|
||||||
isSneaking,
|
|
||||||
isMoving
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player logout event - cleanup animation data.
|
* Player logout event - cleanup animation data.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class NpcAnimationTickHandler {
|
|||||||
* (base posture) and an item layer (GLB-driven bones). Sitting and kneeling are
|
* (base posture) and an item layer (GLB-driven bones). Sitting and kneeling are
|
||||||
* handled by the context resolver, so the V2 path now covers all postures.
|
* handled by the context resolver, so the V2 path now covers all postures.
|
||||||
*
|
*
|
||||||
* <p>V1 fallback: if no V2 GLB model is found, falls back to JSON-based
|
* <p>Legacy fallback: if no GLB model is found, falls back to JSON-based
|
||||||
* PlayerAnimator animations via {@link BondageAnimationManager}.
|
* PlayerAnimator animations via {@link BondageAnimationManager}.
|
||||||
*/
|
*/
|
||||||
private static void updateNpcAnimation(AbstractTiedUpNpc entity) {
|
private static void updateNpcAnimation(AbstractTiedUpNpc entity) {
|
||||||
@@ -120,7 +120,7 @@ public class NpcAnimationTickHandler {
|
|||||||
);
|
);
|
||||||
lastNpcAnimId.remove(uuid);
|
lastNpcAnimId.remove(uuid);
|
||||||
} else {
|
} else {
|
||||||
// V1 fallback: JSON-based PlayerAnimator animations
|
// Legacy fallback: JSON-based PlayerAnimator animations
|
||||||
if (GltfAnimationApplier.hasActiveState(entity)) {
|
if (GltfAnimationApplier.hasActiveState(entity)) {
|
||||||
GltfAnimationApplier.clearV2Animation(entity);
|
GltfAnimationApplier.clearV2Animation(entity);
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ public class NpcAnimationTickHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build animation ID for an NPC from its current state (V1 path).
|
* Build animation ID for an NPC from its current state (legacy JSON path).
|
||||||
*/
|
*/
|
||||||
private static String buildNpcAnimationId(AbstractTiedUpNpc entity) {
|
private static String buildNpcAnimationId(AbstractTiedUpNpc entity) {
|
||||||
// Determine position prefix for SIT/KNEEL poses
|
// Determine position prefix for SIT/KNEEL poses
|
||||||
@@ -175,7 +175,7 @@ public class NpcAnimationTickHandler {
|
|||||||
BodyRegionV2.LEGS
|
BodyRegionV2.LEGS
|
||||||
);
|
);
|
||||||
|
|
||||||
// V1 fallback: if no V2 regions set but NPC has a bind, derive from bind mode NBT
|
// Legacy fallback: if no V2 regions set but NPC has a bind, derive from bind mode NBT
|
||||||
if (!armsBound && !legsBound && BindModeHelper.isBindItem(bind)) {
|
if (!armsBound && !legsBound && BindModeHelper.isBindItem(bind)) {
|
||||||
armsBound = BindModeHelper.hasArmsBound(bind);
|
armsBound = BindModeHelper.hasArmsBound(bind);
|
||||||
legsBound = BindModeHelper.hasLegsBound(bind);
|
legsBound = BindModeHelper.hasLegsBound(bind);
|
||||||
|
|||||||
@@ -198,12 +198,12 @@ public abstract class BaseAdjustmentScreen extends BaseScreen {
|
|||||||
int totalWidth = buttonWidth * 3 + MARGIN_S * 2;
|
int totalWidth = buttonWidth * 3 + MARGIN_S * 2;
|
||||||
int actionStartX = this.leftPos + (this.imageWidth - totalWidth) / 2;
|
int actionStartX = this.leftPos + (this.imageWidth - totalWidth) / 2;
|
||||||
|
|
||||||
resetButton = Button.builder(Component.literal("0"), b -> resetValue())
|
resetButton = Button.builder(Component.translatable("gui.tiedup.adjustment.btn.reset"), b -> resetValue())
|
||||||
.bounds(actionStartX, actionY, buttonWidth, BUTTON_HEIGHT)
|
.bounds(actionStartX, actionY, buttonWidth, BUTTON_HEIGHT)
|
||||||
.build();
|
.build();
|
||||||
this.addRenderableWidget(resetButton);
|
this.addRenderableWidget(resetButton);
|
||||||
|
|
||||||
decrementButton = Button.builder(Component.literal("-0.25"), b ->
|
decrementButton = Button.builder(Component.translatable("gui.tiedup.adjustment.btn.decrement"), b ->
|
||||||
slider.decrement()
|
slider.decrement()
|
||||||
)
|
)
|
||||||
.bounds(
|
.bounds(
|
||||||
@@ -215,7 +215,7 @@ public abstract class BaseAdjustmentScreen extends BaseScreen {
|
|||||||
.build();
|
.build();
|
||||||
this.addRenderableWidget(decrementButton);
|
this.addRenderableWidget(decrementButton);
|
||||||
|
|
||||||
incrementButton = Button.builder(Component.literal("+0.25"), b ->
|
incrementButton = Button.builder(Component.translatable("gui.tiedup.adjustment.btn.increment"), b ->
|
||||||
slider.increment()
|
slider.increment()
|
||||||
)
|
)
|
||||||
.bounds(
|
.bounds(
|
||||||
@@ -235,14 +235,14 @@ public abstract class BaseAdjustmentScreen extends BaseScreen {
|
|||||||
int totalWidth = buttonWidth * 3 + MARGIN_S * 2;
|
int totalWidth = buttonWidth * 3 + MARGIN_S * 2;
|
||||||
int scaleStartX = this.leftPos + (this.imageWidth - totalWidth) / 2;
|
int scaleStartX = this.leftPos + (this.imageWidth - totalWidth) / 2;
|
||||||
|
|
||||||
scaleResetButton = Button.builder(Component.literal("1x"), b ->
|
scaleResetButton = Button.builder(Component.translatable("gui.tiedup.adjustment.btn.scale_reset"), b ->
|
||||||
applyScale(AdjustmentHelper.DEFAULT_SCALE)
|
applyScale(AdjustmentHelper.DEFAULT_SCALE)
|
||||||
)
|
)
|
||||||
.bounds(scaleStartX, scaleY, buttonWidth, BUTTON_HEIGHT)
|
.bounds(scaleStartX, scaleY, buttonWidth, BUTTON_HEIGHT)
|
||||||
.build();
|
.build();
|
||||||
this.addRenderableWidget(scaleResetButton);
|
this.addRenderableWidget(scaleResetButton);
|
||||||
|
|
||||||
scaleDecrementButton = Button.builder(Component.literal("-0.1"), b ->
|
scaleDecrementButton = Button.builder(Component.translatable("gui.tiedup.adjustment.btn.scale_decrement"), b ->
|
||||||
applyScale(currentScaleValue - AdjustmentHelper.SCALE_STEP)
|
applyScale(currentScaleValue - AdjustmentHelper.SCALE_STEP)
|
||||||
)
|
)
|
||||||
.bounds(
|
.bounds(
|
||||||
@@ -254,7 +254,7 @@ public abstract class BaseAdjustmentScreen extends BaseScreen {
|
|||||||
.build();
|
.build();
|
||||||
this.addRenderableWidget(scaleDecrementButton);
|
this.addRenderableWidget(scaleDecrementButton);
|
||||||
|
|
||||||
scaleIncrementButton = Button.builder(Component.literal("+0.1"), b ->
|
scaleIncrementButton = Button.builder(Component.translatable("gui.tiedup.adjustment.btn.scale_increment"), b ->
|
||||||
applyScale(currentScaleValue + AdjustmentHelper.SCALE_STEP)
|
applyScale(currentScaleValue + AdjustmentHelper.SCALE_STEP)
|
||||||
)
|
)
|
||||||
.bounds(
|
.bounds(
|
||||||
|
|||||||
@@ -565,7 +565,7 @@ public class CellManagerScreen extends BaseScreen {
|
|||||||
if (cell.prisoners.isEmpty()) {
|
if (cell.prisoners.isEmpty()) {
|
||||||
graphics.drawString(
|
graphics.drawString(
|
||||||
this.font,
|
this.font,
|
||||||
Component.literal(" \u2514\u2500 ")
|
Component.translatable("gui.tiedup.cell_manager.tree_prefix")
|
||||||
.append(
|
.append(
|
||||||
Component.translatable(
|
Component.translatable(
|
||||||
"gui.tiedup.cell_manager.label.empty"
|
"gui.tiedup.cell_manager.label.empty"
|
||||||
|
|||||||
@@ -548,12 +548,9 @@ public class CommandWandScreen extends Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addFollowDistanceCycleButton(int x, int y, int width) {
|
private void addFollowDistanceCycleButton(int x, int y, int width) {
|
||||||
String modeText = switch (followDistanceMode) {
|
Component modeLabel = Component.translatable(
|
||||||
case "HEEL" -> "H";
|
"gui.tiedup.command_wand.follow_distance.abbrev." + followDistanceMode.toLowerCase()
|
||||||
case "CLOSE" -> "C";
|
);
|
||||||
case "FAR" -> "F";
|
|
||||||
default -> "?";
|
|
||||||
};
|
|
||||||
|
|
||||||
Component tooltip = Component.translatable(
|
Component tooltip = Component.translatable(
|
||||||
"gui.tiedup.command_wand.follow_distance.tooltip"
|
"gui.tiedup.command_wand.follow_distance.tooltip"
|
||||||
@@ -571,7 +568,7 @@ public class CommandWandScreen extends Screen {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
Button btn = Button.builder(Component.literal(modeText), b ->
|
Button btn = Button.builder(modeLabel, b ->
|
||||||
cycleFollowDistance()
|
cycleFollowDistance()
|
||||||
)
|
)
|
||||||
.bounds(x, y, width, BUTTON_HEIGHT)
|
.bounds(x, y, width, BUTTON_HEIGHT)
|
||||||
@@ -857,7 +854,7 @@ public class CommandWandScreen extends Screen {
|
|||||||
) {
|
) {
|
||||||
graphics.renderTooltip(
|
graphics.renderTooltip(
|
||||||
this.font,
|
this.font,
|
||||||
Component.literal((int) hunger + "%"),
|
Component.translatable("gui.tiedup.command_wand.percent", (int) hunger),
|
||||||
mouseX,
|
mouseX,
|
||||||
mouseY
|
mouseY
|
||||||
);
|
);
|
||||||
@@ -871,7 +868,7 @@ public class CommandWandScreen extends Screen {
|
|||||||
) {
|
) {
|
||||||
graphics.renderTooltip(
|
graphics.renderTooltip(
|
||||||
this.font,
|
this.font,
|
||||||
Component.literal((int) rest + "%"),
|
Component.translatable("gui.tiedup.command_wand.percent", (int) rest),
|
||||||
mouseX,
|
mouseX,
|
||||||
mouseY
|
mouseY
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -216,24 +216,24 @@ public class MerchantTradingScreen extends BaseScreen {
|
|||||||
int goldIngots = countItemInInventory(player, Items.GOLD_INGOT);
|
int goldIngots = countItemInInventory(player, Items.GOLD_INGOT);
|
||||||
int goldNuggets = countItemInInventory(player, Items.GOLD_NUGGET);
|
int goldNuggets = countItemInInventory(player, Items.GOLD_NUGGET);
|
||||||
|
|
||||||
Component goldText = Component.literal("Your Gold: ")
|
Component goldText = Component.translatable("gui.tiedup.merchant.your_gold")
|
||||||
.append(
|
.append(
|
||||||
Component.literal(goldIngots + "x ").withStyle(style ->
|
Component.translatable("gui.tiedup.merchant.gold_amount", goldIngots).withStyle(style ->
|
||||||
style.withColor(0xFFFFD700)
|
style.withColor(0xFFFFD700)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
Component.literal("⚜ ").withStyle(style ->
|
Component.translatable("gui.tiedup.merchant.gold_icon").withStyle(style ->
|
||||||
style.withColor(0xFFFFD700)
|
style.withColor(0xFFFFD700)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
Component.literal("+ " + goldNuggets + "x ").withStyle(
|
Component.translatable("gui.tiedup.merchant.nugget_amount", goldNuggets).withStyle(
|
||||||
style -> style.withColor(0xFFFFA500)
|
style -> style.withColor(0xFFFFA500)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
Component.literal("✦").withStyle(style ->
|
Component.translatable("gui.tiedup.merchant.nugget_icon").withStyle(style ->
|
||||||
style.withColor(0xFFFFA500)
|
style.withColor(0xFFFFA500)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class NpcInventoryScreen
|
|||||||
Inventory playerInventory,
|
Inventory playerInventory,
|
||||||
Component title
|
Component title
|
||||||
) {
|
) {
|
||||||
super(menu, playerInventory, Component.literal(menu.getNpcName()));
|
super(menu, playerInventory, Component.translatable("gui.tiedup.npc_inventory.title_name", menu.getNpcName()));
|
||||||
// Calculate rows from NPC inventory size
|
// Calculate rows from NPC inventory size
|
||||||
this.npcRows = (menu.getNpcSlotCount() + 8) / 9;
|
this.npcRows = (menu.getNpcSlotCount() + 8) / 9;
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public class ActionPanel extends AbstractWidget {
|
|||||||
private int hoveredIndex = -1;
|
private int hoveredIndex = -1;
|
||||||
|
|
||||||
public ActionPanel(int x, int y, int width, int height) {
|
public ActionPanel(int x, int y, int width, int height) {
|
||||||
super(x, y, width, height, Component.literal("Actions"));
|
super(x, y, width, height, Component.translatable("gui.tiedup.action_panel"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMode(ScreenMode mode) {
|
public void setMode(ScreenMode mode) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class ItemPickerOverlay extends AbstractWidget {
|
|||||||
private int screenHeight;
|
private int screenHeight;
|
||||||
|
|
||||||
public ItemPickerOverlay() {
|
public ItemPickerOverlay() {
|
||||||
super(0, 0, 0, 0, Component.literal("Item Picker"));
|
super(0, 0, 0, 0, Component.translatable("gui.tiedup.item_picker"));
|
||||||
this.active = false;
|
this.active = false;
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public class RegionTabBar extends AbstractWidget {
|
|||||||
private LivingEntity targetEntity;
|
private LivingEntity targetEntity;
|
||||||
|
|
||||||
public RegionTabBar(int x, int y, int width) {
|
public RegionTabBar(int x, int y, int width) {
|
||||||
super(x, y, width, TAB_HEIGHT, Component.literal("Tab Bar"));
|
super(x, y, width, TAB_HEIGHT, Component.translatable("gui.tiedup.tab_bar.label"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnTabChanged(Consumer<BodyTab> callback) {
|
public void setOnTabChanged(Consumer<BodyTab> callback) {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class StatusBarWidget extends AbstractWidget {
|
|||||||
private static final int CLOSE_BTN_HEIGHT = 22;
|
private static final int CLOSE_BTN_HEIGHT = 22;
|
||||||
|
|
||||||
public StatusBarWidget(int x, int y, int width, int height) {
|
public StatusBarWidget(int x, int y, int width, int height) {
|
||||||
super(x, y, width, height, Component.literal("Status Bar"));
|
super(x, y, width, height, Component.translatable("gui.tiedup.status_bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMode(ActionPanel.ScreenMode mode) {
|
public void setMode(ActionPanel.ScreenMode mode) {
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ public class MCACompatEvents {
|
|||||||
IBondageState state = MCACompat.getKidnappedState(livingTarget);
|
IBondageState state = MCACompat.getKidnappedState(livingTarget);
|
||||||
if (state != null) {
|
if (state != null) {
|
||||||
// Priority: Untie > Ungag > Unblindfold > etc.
|
// Priority: Untie > Ungag > Unblindfold > etc.
|
||||||
// This mimics EntityDamsel logic or ItemBind.interactLivingEntity logic for untying
|
// This mimics EntityDamsel logic or TyingInteractionHelper logic for untying
|
||||||
|
|
||||||
// No collar ownership check — any player can untie MCA villagers by design
|
// No collar ownership check — any player can untie MCA villagers by design
|
||||||
// (MCA villagers use a separate relationship system, not TiedUp collars)
|
// (MCA villagers use a separate relationship system, not TiedUp collars)
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ public class SettingsAccessor {
|
|||||||
* <p><b>BUG-003 fix:</b> Previously, {@code IHasResistance.getBaseResistance()}
|
* <p><b>BUG-003 fix:</b> Previously, {@code IHasResistance.getBaseResistance()}
|
||||||
* called {@code ModGameRules.getResistance()} which only knew 4 types (rope, gag,
|
* called {@code ModGameRules.getResistance()} which only knew 4 types (rope, gag,
|
||||||
* blindfold, collar) and returned hardcoded 100 for the other 10 types. Meanwhile
|
* blindfold, collar) and returned hardcoded 100 for the other 10 types. Meanwhile
|
||||||
* the old BindVariant.getResistance() read from ModConfig which had all 14 types.
|
* the old {@code BindVariant.getResistance()} (now removed) read from ModConfig which had all 14 types.
|
||||||
* This caused a display-vs-struggle desync (display: 250, struggle: 100).
|
* This caused a display-vs-struggle desync (display: 250, struggle: 100).
|
||||||
* Now both paths use this method.
|
* Now both paths use this method.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class PetRequestManager {
|
|||||||
double dist = master.distanceTo(pet);
|
double dist = master.distanceTo(pet);
|
||||||
if (dist > MAX_DISTANCE) {
|
if (dist > MAX_DISTANCE) {
|
||||||
pet.sendSystemMessage(
|
pet.sendSystemMessage(
|
||||||
Component.literal("You are too far from your Master to talk.")
|
Component.translatable("entity.tiedup.pet.too_far_to_talk")
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ public class PetRequestManager {
|
|||||||
double dist = master.distanceTo(pet);
|
double dist = master.distanceTo(pet);
|
||||||
if (dist > MAX_DISTANCE) {
|
if (dist > MAX_DISTANCE) {
|
||||||
pet.sendSystemMessage(
|
pet.sendSystemMessage(
|
||||||
Component.literal("You are too far from your Master.")
|
Component.translatable("entity.tiedup.pet.too_far_from_master")
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ public class PetRequestManager {
|
|||||||
|
|
||||||
// Display what the player "says"
|
// Display what the player "says"
|
||||||
pet.sendSystemMessage(
|
pet.sendSystemMessage(
|
||||||
Component.literal("You: " + request.getPlayerText())
|
Component.translatable("entity.tiedup.pet.you_say", request.getPlayerText())
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle specific request
|
// Handle specific request
|
||||||
|
|||||||
@@ -644,8 +644,8 @@ public class EntityDamsel
|
|||||||
player instanceof net.minecraft.server.level.ServerPlayer sp
|
player instanceof net.minecraft.server.level.ServerPlayer sp
|
||||||
) {
|
) {
|
||||||
sp.displayClientMessage(
|
sp.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"This NPC needs a collar before you can feed them."
|
"entity.tiedup.damsel.needs_collar_to_feed"
|
||||||
).withStyle(ChatFormatting.RED),
|
).withStyle(ChatFormatting.RED),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
@@ -660,8 +660,8 @@ public class EntityDamsel
|
|||||||
net.minecraft.server.level.ServerPlayer sp
|
net.minecraft.server.level.ServerPlayer sp
|
||||||
) {
|
) {
|
||||||
sp.displayClientMessage(
|
sp.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You don't own this NPC's collar."
|
"entity.tiedup.damsel.not_collar_owner"
|
||||||
).withStyle(ChatFormatting.RED),
|
).withStyle(ChatFormatting.RED),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
@@ -675,8 +675,8 @@ public class EntityDamsel
|
|||||||
player instanceof net.minecraft.server.level.ServerPlayer sp
|
player instanceof net.minecraft.server.level.ServerPlayer sp
|
||||||
) {
|
) {
|
||||||
sp.displayClientMessage(
|
sp.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"This NPC can't eat that right now."
|
"entity.tiedup.damsel.cant_eat_now"
|
||||||
).withStyle(ChatFormatting.RED),
|
).withStyle(ChatFormatting.RED),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ public class EntityLaborGuard extends EntityDamsel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal("Attacking your guard is punished!").withStyle(
|
Component.translatable("entity.tiedup.guard.attack_punished").withStyle(
|
||||||
ChatFormatting.DARK_RED
|
ChatFormatting.DARK_RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -529,8 +529,8 @@ public class EntityLaborGuard extends EntityDamsel {
|
|||||||
.getPlayer(prisonerUUID);
|
.getPlayer(prisonerUUID);
|
||||||
if (prisoner != null) {
|
if (prisoner != null) {
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Your guard has been eliminated! You are free!"
|
"entity.tiedup.guard.eliminated_free"
|
||||||
).withStyle(ChatFormatting.GREEN, ChatFormatting.BOLD)
|
).withStyle(ChatFormatting.GREEN, ChatFormatting.BOLD)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -447,8 +447,8 @@ public class EntityMaid extends EntityKidnapperElite {
|
|||||||
player.position().distanceTo(this.position()) <= 50
|
player.position().distanceTo(this.position()) <= 50
|
||||||
) {
|
) {
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"The maid has died. Work is paused. A replacement will arrive in 5 minutes."
|
"entity.tiedup.maid.died_work_paused"
|
||||||
).withStyle(net.minecraft.ChatFormatting.GOLD)
|
).withStyle(net.minecraft.ChatFormatting.GOLD)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -606,8 +606,8 @@ public class EntityMaster extends EntityKidnapperElite {
|
|||||||
|
|
||||||
// Send warning message to pet
|
// Send warning message to pet
|
||||||
pet.sendSystemMessage(
|
pet.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
this.getNpcName() + " caught you trying to escape!"
|
"entity.tiedup.master.caught_escaping", this.getNpcName()
|
||||||
).withStyle(Style.EMPTY.withColor(MASTER_NAME_COLOR))
|
).withStyle(Style.EMPTY.withColor(MASTER_NAME_COLOR))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,8 +200,8 @@ public class EntitySlaveTrader extends EntityKidnapperElite {
|
|||||||
Component.literal("[" + this.getNpcName() + "] ")
|
Component.literal("[" + this.getNpcName() + "] ")
|
||||||
.withStyle(Style.EMPTY.withColor(TRADER_NAME_COLOR))
|
.withStyle(Style.EMPTY.withColor(TRADER_NAME_COLOR))
|
||||||
.append(
|
.append(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You don't have a trader token. Leave now, or I'll make you leave."
|
"entity.tiedup.trader.no_token_warning"
|
||||||
).withStyle(ChatFormatting.RED)
|
).withStyle(ChatFormatting.RED)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -711,8 +711,8 @@ public class EntitySlaveTrader extends EntityKidnapperElite {
|
|||||||
ServerLevel level,
|
ServerLevel level,
|
||||||
BlockPos campCenter
|
BlockPos campCenter
|
||||||
) {
|
) {
|
||||||
Component message = Component.literal(
|
Component message = Component.translatable(
|
||||||
"A slave trader camp has been destroyed!"
|
"entity.tiedup.trader.camp_destroyed"
|
||||||
).withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD);
|
).withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD);
|
||||||
|
|
||||||
// Send to all players within 200 blocks
|
// Send to all players within 200 blocks
|
||||||
|
|||||||
@@ -93,15 +93,15 @@ public class MerchantTrade {
|
|||||||
*/
|
*/
|
||||||
public Component getPriceDisplay() {
|
public Component getPriceDisplay() {
|
||||||
if (ingotPrice > 0 && nuggetPrice > 0) {
|
if (ingotPrice > 0 && nuggetPrice > 0) {
|
||||||
return Component.literal(
|
return Component.translatable(
|
||||||
ingotPrice + " gold + " + nuggetPrice + " nuggets"
|
"entity.tiedup.trade.price_both", ingotPrice, nuggetPrice
|
||||||
);
|
);
|
||||||
} else if (ingotPrice > 0) {
|
} else if (ingotPrice > 0) {
|
||||||
return Component.literal(ingotPrice + " gold");
|
return Component.translatable("entity.tiedup.trade.price_gold", ingotPrice);
|
||||||
} else if (nuggetPrice > 0) {
|
} else if (nuggetPrice > 0) {
|
||||||
return Component.literal(nuggetPrice + " nuggets");
|
return Component.translatable("entity.tiedup.trade.price_nuggets", nuggetPrice);
|
||||||
} else {
|
} else {
|
||||||
return Component.literal("Free");
|
return Component.translatable("entity.tiedup.trade.price_free");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,8 +202,8 @@ public class GuardMonitorGoal extends Goal {
|
|||||||
);
|
);
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You are too far from your guard! Return within 15 seconds or escape will be triggered!"
|
"goal.tiedup.guard_monitor.too_far"
|
||||||
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -227,8 +227,8 @@ public class GuardMonitorGoal extends Goal {
|
|||||||
);
|
);
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You returned to your guard. Stay close!"
|
"goal.tiedup.guard_monitor.returned"
|
||||||
).withStyle(ChatFormatting.YELLOW)
|
).withStyle(ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -604,8 +604,8 @@ public class KidnapperDecideNextActionGoal extends Goal {
|
|||||||
);
|
);
|
||||||
|
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You're still tied up - struggle to break free!"
|
"goal.tiedup.kidnapper_decide.still_tied"
|
||||||
).withStyle(ChatFormatting.YELLOW)
|
).withStyle(ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -351,14 +351,14 @@ public class KidnapperWaitForBuyerGoal extends Goal {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Component announcement = Component.literal("")
|
Component announcement = Component.literal("")
|
||||||
.append(Component.literal("[SALE] ").withStyle(ChatFormatting.GOLD))
|
.append(Component.translatable("goal.tiedup.kidnapper_sale.tag").withStyle(ChatFormatting.GOLD))
|
||||||
.append(
|
.append(
|
||||||
Component.literal(this.kidnapper.getNpcName()).withStyle(
|
Component.literal(this.kidnapper.getNpcName()).withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
Component.literal(" is selling ").withStyle(
|
Component.translatable("goal.tiedup.kidnapper_sale.is_selling").withStyle(
|
||||||
ChatFormatting.YELLOW
|
ChatFormatting.YELLOW
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -367,13 +367,13 @@ public class KidnapperWaitForBuyerGoal extends Goal {
|
|||||||
ChatFormatting.AQUA
|
ChatFormatting.AQUA
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(Component.literal(" for ").withStyle(ChatFormatting.YELLOW))
|
.append(Component.translatable("goal.tiedup.kidnapper_sale.for").withStyle(ChatFormatting.YELLOW))
|
||||||
.append(
|
.append(
|
||||||
Component.literal(price.toDisplayString()).withStyle(
|
Component.literal(price.toDisplayString()).withStyle(
|
||||||
ChatFormatting.GREEN
|
ChatFormatting.GREEN
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(Component.literal(" at ").withStyle(ChatFormatting.YELLOW))
|
.append(Component.translatable("goal.tiedup.kidnapper_sale.at").withStyle(ChatFormatting.YELLOW))
|
||||||
.append(
|
.append(
|
||||||
Component.literal(location).withStyle(ChatFormatting.WHITE)
|
Component.literal(location).withStyle(ChatFormatting.WHITE)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -331,9 +331,9 @@ public class MaidDeliverCaptiveGoal extends Goal {
|
|||||||
buyerEntity.getName().getString()
|
buyerEntity.getName().getString()
|
||||||
);
|
);
|
||||||
buyerEntity.sendSystemMessage(
|
buyerEntity.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
captiveEntity.getName().getString() +
|
"goal.tiedup.maid_deliver.on_leash",
|
||||||
" is now on your leash."
|
captiveEntity.getName().getString()
|
||||||
).withStyle(net.minecraft.ChatFormatting.GREEN)
|
).withStyle(net.minecraft.ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -342,9 +342,9 @@ public class MaidDeliverCaptiveGoal extends Goal {
|
|||||||
);
|
);
|
||||||
kidnappedState.free(true);
|
kidnappedState.free(true);
|
||||||
buyerEntity.sendSystemMessage(
|
buyerEntity.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
captiveEntity.getName().getString() +
|
"goal.tiedup.maid_deliver.delivered",
|
||||||
" has been delivered to you."
|
captiveEntity.getName().getString()
|
||||||
).withStyle(net.minecraft.ChatFormatting.GREEN)
|
).withStyle(net.minecraft.ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,13 +200,13 @@ public class MaidAssignTaskGoal extends Goal {
|
|||||||
|
|
||||||
// Notify prisoner
|
// Notify prisoner
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Task assigned: " + task.getDescription()
|
"goal.tiedup.maid_assign.task_assigned", task.getDescription()
|
||||||
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Reward: " + task.getValue() + " emeralds toward your debt."
|
"goal.tiedup.maid_assign.task_reward", task.getValue()
|
||||||
).withStyle(net.minecraft.ChatFormatting.GRAY)
|
).withStyle(net.minecraft.ChatFormatting.GRAY)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -289,8 +289,8 @@ public class MaidAssignTaskGoal extends Goal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Your debt is paid. You are FREE!"
|
"goal.tiedup.maid.debt_paid_free"
|
||||||
).withStyle(
|
).withStyle(
|
||||||
net.minecraft.ChatFormatting.GREEN,
|
net.minecraft.ChatFormatting.GREEN,
|
||||||
net.minecraft.ChatFormatting.BOLD
|
net.minecraft.ChatFormatting.BOLD
|
||||||
|
|||||||
@@ -346,8 +346,8 @@ public class MaidExtractGoal extends Goal {
|
|||||||
|
|
||||||
// 7. Notify prisoner
|
// 7. Notify prisoner
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"You have been extracted for labor. Complete your task: " +
|
"goal.tiedup.maid_extract.extracted",
|
||||||
task.getDescription()
|
task.getDescription()
|
||||||
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ public class MaidIdleGoal extends Goal {
|
|||||||
labor.completeTask(currentTime);
|
labor.completeTask(currentTime);
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Task complete! Walk back to camp."
|
"goal.tiedup.maid_idle.task_complete"
|
||||||
).withStyle(net.minecraft.ChatFormatting.GREEN)
|
).withStyle(net.minecraft.ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -207,17 +207,16 @@ public class MaidIdleGoal extends Goal {
|
|||||||
// Max punishment - fail task
|
// Max punishment - fail task
|
||||||
labor.failTask(currentTime);
|
labor.failTask(currentTime);
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Task failed due to inactivity! You will be returned to your cell."
|
"goal.tiedup.maid_idle.task_failed"
|
||||||
).withStyle(net.minecraft.ChatFormatting.RED)
|
).withStyle(net.minecraft.ChatFormatting.RED)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Warning
|
// Warning
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Warning: Work or face punishment! (" +
|
"goal.tiedup.maid_idle.inactivity_warning",
|
||||||
shockLevel +
|
shockLevel
|
||||||
"/3)"
|
|
||||||
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -165,18 +165,16 @@ public class MaidInitPrisonerGoal extends Goal {
|
|||||||
|
|
||||||
// 6. Notify prisoner
|
// 6. Notify prisoner
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
String.format(
|
"goal.tiedup.maid_init.imprisoned",
|
||||||
"You have been imprisoned. Your debt: %d emeralds.",
|
|
||||||
totalRansom
|
totalRansom
|
||||||
)
|
|
||||||
).withStyle(net.minecraft.ChatFormatting.RED)
|
).withStyle(net.minecraft.ChatFormatting.RED)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!confiscated.isEmpty()) {
|
if (!confiscated.isEmpty()) {
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Your valuables have been confiscated."
|
"goal.tiedup.maid_init.confiscated"
|
||||||
).withStyle(net.minecraft.ChatFormatting.GRAY)
|
).withStyle(net.minecraft.ChatFormatting.GRAY)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -671,8 +671,8 @@ public class MaidReturnGoal extends Goal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"Your debt is paid. You are FREE!"
|
"goal.tiedup.maid.debt_paid_free"
|
||||||
).withStyle(
|
).withStyle(
|
||||||
net.minecraft.ChatFormatting.GREEN,
|
net.minecraft.ChatFormatting.GREEN,
|
||||||
net.minecraft.ChatFormatting.BOLD
|
net.minecraft.ChatFormatting.BOLD
|
||||||
|
|||||||
@@ -124,11 +124,10 @@ public class MasterInventoryInspectGoal extends Goal {
|
|||||||
ServerPlayer pet = master.getPetPlayer();
|
ServerPlayer pet = master.getPetPlayer();
|
||||||
if (pet != null && !confiscatedItems.isEmpty()) {
|
if (pet != null && !confiscatedItems.isEmpty()) {
|
||||||
pet.sendSystemMessage(
|
pet.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
master.getNpcName() +
|
"goal.tiedup.master_inspect.confiscated",
|
||||||
" confiscated " +
|
master.getNpcName(),
|
||||||
confiscatedItems.size() +
|
confiscatedItems.size()
|
||||||
" contraband item(s) from you!"
|
|
||||||
).withStyle(
|
).withStyle(
|
||||||
Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR)
|
Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR)
|
||||||
)
|
)
|
||||||
@@ -180,8 +179,8 @@ public class MasterInventoryInspectGoal extends Goal {
|
|||||||
*/
|
*/
|
||||||
private void performInspection(ServerPlayer pet) {
|
private void performInspection(ServerPlayer pet) {
|
||||||
pet.sendSystemMessage(
|
pet.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
master.getNpcName() + " is inspecting your inventory..."
|
"goal.tiedup.master_inspect.inspecting", master.getNpcName()
|
||||||
).withStyle(Style.EMPTY.withColor(0xFFFF00))
|
).withStyle(Style.EMPTY.withColor(0xFFFF00))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -331,8 +331,8 @@ public class MasterTaskAssignGoal extends Goal {
|
|||||||
// FIX: Use MessageDispatcher for consistency with earplug system
|
// FIX: Use MessageDispatcher for consistency with earplug system
|
||||||
MessageDispatcher.sendChat(
|
MessageDispatcher.sendChat(
|
||||||
pet,
|
pet,
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
master.getNpcName() + ": \"" + message + "\""
|
"goal.tiedup.master_assign.task_speech", master.getNpcName(), message
|
||||||
).withStyle(Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR))
|
).withStyle(Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -269,8 +269,8 @@ public class MasterTaskWatchGoal extends Goal {
|
|||||||
if (remainingSec > 0) {
|
if (remainingSec > 0) {
|
||||||
MessageDispatcher.sendActionBar(
|
MessageDispatcher.sendActionBar(
|
||||||
pet,
|
pet,
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
task.name() + " - " + remainingSec + "s remaining"
|
"goal.tiedup.master_watch.time_remaining", task.name(), remainingSec
|
||||||
).withStyle(Style.EMPTY.withColor(0xFFAA00))
|
).withStyle(Style.EMPTY.withColor(0xFFAA00))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -357,8 +357,8 @@ public class MasterTaskWatchGoal extends Goal {
|
|||||||
) {
|
) {
|
||||||
MessageDispatcher.sendChat(
|
MessageDispatcher.sendChat(
|
||||||
pet,
|
pet,
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
master.getNpcName() + ": \"I'm waiting...\""
|
"goal.tiedup.master_watch.speak_waiting", master.getNpcName()
|
||||||
).withStyle(
|
).withStyle(
|
||||||
Style.EMPTY.withColor(
|
Style.EMPTY.withColor(
|
||||||
EntityMaster.MASTER_NAME_COLOR
|
EntityMaster.MASTER_NAME_COLOR
|
||||||
@@ -384,8 +384,8 @@ public class MasterTaskWatchGoal extends Goal {
|
|||||||
.nextInt(demandWarnings.length)];
|
.nextInt(demandWarnings.length)];
|
||||||
MessageDispatcher.sendChat(
|
MessageDispatcher.sendChat(
|
||||||
pet,
|
pet,
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
master.getNpcName() + ": \"" + warning + "\""
|
"goal.tiedup.master_watch.demand_warning", master.getNpcName(), warning
|
||||||
).withStyle(
|
).withStyle(
|
||||||
Style.EMPTY.withColor(
|
Style.EMPTY.withColor(
|
||||||
EntityMaster.MASTER_NAME_COLOR
|
EntityMaster.MASTER_NAME_COLOR
|
||||||
@@ -431,8 +431,8 @@ public class MasterTaskWatchGoal extends Goal {
|
|||||||
String message = messages[master.getRandom().nextInt(messages.length)];
|
String message = messages[master.getRandom().nextInt(messages.length)];
|
||||||
MessageDispatcher.sendChat(
|
MessageDispatcher.sendChat(
|
||||||
pet,
|
pet,
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
master.getNpcName() + ": \"" + message + "\""
|
"goal.tiedup.master_watch.punishment", master.getNpcName(), message
|
||||||
).withStyle(Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR))
|
).withStyle(Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -450,8 +450,8 @@ public class NpcGuardCommandGoal extends Goal {
|
|||||||
if (player.getUUID().equals(commanderUUID)) {
|
if (player.getUUID().equals(commanderUUID)) {
|
||||||
String slaveName = slave.getNpcName();
|
String slaveName = slave.getNpcName();
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
npc.getNpcName() + " is chasing " + slaveName + "!"
|
"goal.tiedup.guard_command.chasing", npc.getNpcName(), slaveName
|
||||||
).withStyle(net.minecraft.ChatFormatting.RED),
|
).withStyle(net.minecraft.ChatFormatting.RED),
|
||||||
true // Action bar
|
true // Action bar
|
||||||
);
|
);
|
||||||
@@ -545,8 +545,8 @@ public class NpcGuardCommandGoal extends Goal {
|
|||||||
// Send alert message (could be enhanced with dialogue system)
|
// Send alert message (could be enhanced with dialogue system)
|
||||||
String threatName = threat.getName().getString();
|
String threatName = threat.getName().getString();
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
npc.getNpcName() + " spotted: " + threatName + "!"
|
"goal.tiedup.guard_command.spotted", npc.getNpcName(), threatName
|
||||||
).withStyle(net.minecraft.ChatFormatting.YELLOW),
|
).withStyle(net.minecraft.ChatFormatting.YELLOW),
|
||||||
true // Action bar
|
true // Action bar
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -185,13 +185,13 @@ public class TraderSellGoal extends Goal {
|
|||||||
);
|
);
|
||||||
|
|
||||||
potentialBuyer.sendSystemMessage(
|
potentialBuyer.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"[" + trader.getNpcName() + "] " + greeting
|
"goal.tiedup.trader_sell.greeting", trader.getNpcName(), greeting
|
||||||
).withStyle(net.minecraft.ChatFormatting.GOLD)
|
).withStyle(net.minecraft.ChatFormatting.GOLD)
|
||||||
);
|
);
|
||||||
|
|
||||||
potentialBuyer.sendSystemMessage(
|
potentialBuyer.sendSystemMessage(
|
||||||
Component.literal("Right-click me to browse my stock.").withStyle(
|
Component.translatable("goal.tiedup.trader_sell.browse_hint").withStyle(
|
||||||
net.minecraft.ChatFormatting.GRAY
|
net.minecraft.ChatFormatting.GRAY
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -165,8 +165,8 @@ public class MaidPrisonInteraction {
|
|||||||
|
|
||||||
sayToPlayer(player, "Very well. Here are your tools.");
|
sayToPlayer(player, "Very well. Here are your tools.");
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"The maid manually assigns you to: " + task.getDescription()
|
"entity.tiedup.maid.manual_assign", task.getDescription()
|
||||||
).withStyle(ChatFormatting.YELLOW)
|
).withStyle(ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -206,8 +206,8 @@ public class MaidPrisonInteraction {
|
|||||||
|
|
||||||
sayToPlayer(worker, "Good. You've completed your task.");
|
sayToPlayer(worker, "Good. You've completed your task.");
|
||||||
worker.sendSystemMessage(
|
worker.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"A Maid will come to collect you shortly."
|
"entity.tiedup.maid.collect_shortly"
|
||||||
).withStyle(ChatFormatting.YELLOW)
|
).withStyle(ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -229,13 +229,13 @@ public class MaidPrisonInteraction {
|
|||||||
@Nullable LaborRecord laborRecord
|
@Nullable LaborRecord laborRecord
|
||||||
) {
|
) {
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal("=== Labor Status ===").withStyle(
|
Component.translatable("entity.tiedup.maid.labor_status_header").withStyle(
|
||||||
ChatFormatting.GOLD
|
ChatFormatting.GOLD
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal("State: " + record.getState().name()).withStyle(
|
Component.translatable("entity.tiedup.maid.labor_status_state", record.getState().name()).withStyle(
|
||||||
ChatFormatting.GRAY
|
ChatFormatting.GRAY
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -243,13 +243,13 @@ public class MaidPrisonInteraction {
|
|||||||
if (laborRecord != null && laborRecord.getTask() != null) {
|
if (laborRecord != null && laborRecord.getTask() != null) {
|
||||||
LaborTask task = laborRecord.getTask();
|
LaborTask task = laborRecord.getTask();
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal("Task: " + task.getDescription()).withStyle(
|
Component.translatable("entity.tiedup.maid.labor_status_task", task.getDescription()).withStyle(
|
||||||
ChatFormatting.GRAY
|
ChatFormatting.GRAY
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Progress: " + task.getProgress() + "/" + task.getQuota()
|
"entity.tiedup.maid.labor_status_progress", task.getProgress(), task.getQuota()
|
||||||
).withStyle(ChatFormatting.GRAY)
|
).withStyle(ChatFormatting.GRAY)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -262,8 +262,8 @@ public class MaidPrisonInteraction {
|
|||||||
RansomRecord ransom = manager.getRansomRecord(player.getUUID());
|
RansomRecord ransom = manager.getRansomRecord(player.getUUID());
|
||||||
int remaining = ransom != null ? ransom.getRemainingDebt() : 0;
|
int remaining = ransom != null ? ransom.getRemainingDebt() : 0;
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Remaining debt: " + remaining + " emeralds"
|
"entity.tiedup.maid.labor_status_debt", remaining
|
||||||
).withStyle(ChatFormatting.GRAY)
|
).withStyle(ChatFormatting.GRAY)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -273,8 +273,8 @@ public class MaidPrisonInteraction {
|
|||||||
laborRecord.getPhase() == LaborRecord.WorkPhase.PENDING_EXTRACTION
|
laborRecord.getPhase() == LaborRecord.WorkPhase.PENDING_EXTRACTION
|
||||||
) {
|
) {
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Shift+Right-Click to manually start task"
|
"entity.tiedup.maid.labor_hint_start_task"
|
||||||
).withStyle(ChatFormatting.YELLOW)
|
).withStyle(ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
@@ -283,8 +283,8 @@ public class MaidPrisonInteraction {
|
|||||||
laborRecord.getTask().isComplete()
|
laborRecord.getTask().isComplete()
|
||||||
) {
|
) {
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Shift+Right-Click to manually turn in task"
|
"entity.tiedup.maid.labor_hint_turn_in"
|
||||||
).withStyle(ChatFormatting.GREEN)
|
).withStyle(ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,8 +199,8 @@ public class MasterPetManager {
|
|||||||
|
|
||||||
// Send message to player
|
// Send message to player
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You are free! Your master " + master.getNpcName() + " is gone."
|
"entity.tiedup.master.pet_freed", master.getNpcName()
|
||||||
).withStyle(Style.EMPTY.withColor(0x00FF00))
|
).withStyle(Style.EMPTY.withColor(0x00FF00))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ public class CampChestHandler {
|
|||||||
|
|
||||||
if (entity instanceof Player player) {
|
if (entity instanceof Player player) {
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"This chest is locked by the camp!"
|
"msg.tiedup.event.chest_locked_by_camp"
|
||||||
).withStyle(ChatFormatting.RED),
|
).withStyle(ChatFormatting.RED),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -286,10 +286,9 @@ public class CampManagementHandler {
|
|||||||
.getPlayer(prisonerId);
|
.getPlayer(prisonerId);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"A new maid, " +
|
"msg.tiedup.event.new_maid_arrived",
|
||||||
maidName +
|
maidName
|
||||||
", has arrived. Work resumes."
|
|
||||||
).withStyle(ChatFormatting.GOLD)
|
).withStyle(ChatFormatting.GOLD)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,10 +75,10 @@ public class CampNpcProtectionHandler {
|
|||||||
|
|
||||||
// Send warning message to player
|
// Send warning message to player
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
isTrader
|
isTrader
|
||||||
? "The camp defends their leader! You are now under attack!"
|
? "msg.tiedup.event.camp_defends_trader"
|
||||||
: "The camp defends their servant! You are now under attack!"
|
: "msg.tiedup.event.camp_defends_maid"
|
||||||
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ public class GraceEventHandler {
|
|||||||
record.setProtectionExpiry(0);
|
record.setProtectionExpiry(0);
|
||||||
|
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You attacked a kidnapper - protection lost!"
|
"msg.tiedup.event.grace_lost"
|
||||||
).withStyle(ChatFormatting.RED),
|
).withStyle(ChatFormatting.RED),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -209,12 +209,10 @@ public class LaborAttackPunishmentHandler {
|
|||||||
manager.increaseDebt(prisoner.getUUID(), DEBT_INCREASE_PER_ATTACK);
|
manager.increaseDebt(prisoner.getUUID(), DEBT_INCREASE_PER_ATTACK);
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
String.format(
|
"msg.tiedup.event.debt_increased",
|
||||||
"Your debt has increased by %d emeralds for attacking %s!",
|
|
||||||
DEBT_INCREASE_PER_ATTACK,
|
DEBT_INCREASE_PER_ATTACK,
|
||||||
targetName
|
targetName
|
||||||
)
|
|
||||||
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -282,8 +280,8 @@ public class LaborAttackPunishmentHandler {
|
|||||||
|
|
||||||
// 4. Warning message
|
// 4. Warning message
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Your task has been marked as failed. You will not be paid for your work."
|
"msg.tiedup.event.task_failed"
|
||||||
).withStyle(ChatFormatting.DARK_RED)
|
).withStyle(ChatFormatting.DARK_RED)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -315,8 +313,8 @@ public class LaborAttackPunishmentHandler {
|
|||||||
laborRecord.setEscortMaidId(null);
|
laborRecord.setEscortMaidId(null);
|
||||||
|
|
||||||
prisoner.sendSystemMessage(
|
prisoner.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You have been returned to your cell for your insolence!"
|
"msg.tiedup.event.returned_to_cell"
|
||||||
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
).withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -363,8 +363,8 @@ public class PlayerStateEventHandler {
|
|||||||
// Send death escape message if applicable
|
// Send death escape message if applicable
|
||||||
if (pendingDeathEscapeMessage.remove(player.getUUID())) {
|
if (pendingDeathEscapeMessage.remove(player.getUUID())) {
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
net.minecraft.network.chat.Component.literal(
|
net.minecraft.network.chat.Component.translatable(
|
||||||
"You died and escaped captivity. Your items remain in the camp chest."
|
"msg.tiedup.event.death_escape"
|
||||||
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
).withStyle(net.minecraft.ChatFormatting.YELLOW)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ public class BondageItemRestrictionHandler {
|
|||||||
if (state != null && state.isGagged()) {
|
if (state != null && state.isGagged()) {
|
||||||
event.setCanceled(true);
|
event.setCanceled(true);
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal("You can't eat with a gag on.").withStyle(
|
Component.translatable("msg.tiedup.event.cant_eat_gagged").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
),
|
),
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class LaborToolProtectionHandler {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal("You cannot drop labor tools!"),
|
Component.translatable("msg.tiedup.event.cant_drop_labor_tools"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ public class LaborToolProtectionHandler {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal("You cannot store labor tools!"),
|
Component.translatable("msg.tiedup.event.cant_store_labor_tools"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class PetPlayRestrictionHandler {
|
|||||||
|
|
||||||
sendThrottledMessage(
|
sendThrottledMessage(
|
||||||
player,
|
player,
|
||||||
"You cannot eat from your hand! Use a bowl."
|
"msg.tiedup.petplay.cannot_eat_hand"
|
||||||
);
|
);
|
||||||
|
|
||||||
TiedUpMod.LOGGER.debug(
|
TiedUpMod.LOGGER.debug(
|
||||||
@@ -175,7 +175,7 @@ public class PetPlayRestrictionHandler {
|
|||||||
|
|
||||||
sendThrottledMessage(
|
sendThrottledMessage(
|
||||||
player,
|
player,
|
||||||
"You cannot sleep in a bed! Use your pet bed."
|
"msg.tiedup.petplay.cannot_sleep_bed"
|
||||||
);
|
);
|
||||||
|
|
||||||
TiedUpMod.LOGGER.debug(
|
TiedUpMod.LOGGER.debug(
|
||||||
@@ -222,8 +222,8 @@ public class PetPlayRestrictionHandler {
|
|||||||
|
|
||||||
// Start sleeping (simplified - real implementation would need proper sleep mechanics)
|
// Start sleeping (simplified - real implementation would need proper sleep mechanics)
|
||||||
serverPlayer.sendSystemMessage(
|
serverPlayer.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You curl up in your pet bed..."
|
"msg.tiedup.petplay.curl_up_bed"
|
||||||
).withStyle(Style.EMPTY.withColor(0x888888))
|
).withStyle(Style.EMPTY.withColor(0x888888))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ public class PetPlayRestrictionHandler {
|
|||||||
} else {
|
} else {
|
||||||
sendThrottledMessage(
|
sendThrottledMessage(
|
||||||
player,
|
player,
|
||||||
"You can only sleep at night or during thunderstorms."
|
"msg.tiedup.petplay.sleep_time_only"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,14 +325,14 @@ public class PetPlayRestrictionHandler {
|
|||||||
/**
|
/**
|
||||||
* Send a message with cooldown to prevent spam.
|
* Send a message with cooldown to prevent spam.
|
||||||
*/
|
*/
|
||||||
private static void sendThrottledMessage(Player player, String message) {
|
private static void sendThrottledMessage(Player player, String translationKey) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
Long lastTime = lastMessageTime.get(player.getUUID());
|
Long lastTime = lastMessageTime.get(player.getUUID());
|
||||||
|
|
||||||
if (lastTime == null || now - lastTime > MESSAGE_COOLDOWN_MS) {
|
if (lastTime == null || now - lastTime > MESSAGE_COOLDOWN_MS) {
|
||||||
lastMessageTime.put(player.getUUID(), now);
|
lastMessageTime.put(player.getUUID(), now);
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(message).withStyle(
|
Component.translatable(translationKey).withStyle(
|
||||||
Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR)
|
Style.EMPTY.withColor(EntityMaster.MASTER_NAME_COLOR)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class ChatEventHandler {
|
|||||||
|
|
||||||
if (!gagStack.isEmpty() && isGagItem) {
|
if (!gagStack.isEmpty() && isGagItem) {
|
||||||
String originalMessage = event.getRawText();
|
String originalMessage = event.getRawText();
|
||||||
// V2: get material from component, V1 fallback: from ItemGag
|
// V2: get material from GaggingComponent
|
||||||
GagMaterial material = null;
|
GagMaterial material = null;
|
||||||
if (gaggingComp != null) {
|
if (gaggingComp != null) {
|
||||||
material = gaggingComp.getMaterial();
|
material = gaggingComp.getMaterial();
|
||||||
|
|||||||
@@ -75,20 +75,14 @@ public class GenericKnife extends Item implements IKnife {
|
|||||||
|
|
||||||
// Show cutting speed
|
// Show cutting speed
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Cutting speed: " + speed + " res/s").withStyle(
|
Component.translatable("item.tiedup.knife.cutting_speed", speed)
|
||||||
ChatFormatting.GRAY
|
.withStyle(ChatFormatting.GRAY)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Show cutting time remaining
|
// Show cutting time remaining
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal(
|
Component.translatable("item.tiedup.knife.cutting_time", cuttingSeconds, remaining)
|
||||||
"Cutting time: " +
|
.withStyle(ChatFormatting.DARK_GRAY)
|
||||||
cuttingSeconds +
|
|
||||||
"s (" +
|
|
||||||
remaining +
|
|
||||||
" total res)"
|
|
||||||
).withStyle(ChatFormatting.DARK_GRAY)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ public class ItemCellKey extends Item {
|
|||||||
TooltipFlag flag
|
TooltipFlag flag
|
||||||
) {
|
) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Unlocks any Iron Bar Door").withStyle(
|
Component.translatable("item.tiedup.cell_key.desc").withStyle(
|
||||||
ChatFormatting.GRAY
|
ChatFormatting.GRAY
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Does not work on bondage items").withStyle(
|
Component.translatable("item.tiedup.cell_key.restriction").withStyle(
|
||||||
ChatFormatting.DARK_GRAY
|
ChatFormatting.DARK_GRAY
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,13 +39,8 @@ public class ItemGpsLocator extends ItemOwnerTarget {
|
|||||||
if (hasTarget(stack)) {
|
if (hasTarget(stack)) {
|
||||||
String displayName = resolveTargetDisplayName(stack, level);
|
String displayName = resolveTargetDisplayName(stack, level);
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Target: ")
|
Component.translatable("item.tiedup.gps_locator.target", displayName)
|
||||||
.withStyle(ChatFormatting.BLUE)
|
.withStyle(ChatFormatting.BLUE)
|
||||||
.append(
|
|
||||||
Component.literal(displayName).withStyle(
|
|
||||||
ChatFormatting.WHITE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,36 +85,25 @@ public class ItemKey extends ItemOwnerTarget {
|
|||||||
|
|
||||||
if (hasOwner(stack)) {
|
if (hasOwner(stack)) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Owner: ")
|
Component.translatable("item.tiedup.key.owner", getOwnerName(stack))
|
||||||
.withStyle(ChatFormatting.GOLD)
|
.withStyle(ChatFormatting.GOLD)
|
||||||
.append(
|
|
||||||
Component.literal(getOwnerName(stack)).withStyle(
|
|
||||||
ChatFormatting.WHITE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal(
|
Component.translatable("item.tiedup.key.unclaimed")
|
||||||
"Unclaimed (Right-click a collar wearer to claim)"
|
.withStyle(ChatFormatting.GRAY)
|
||||||
).withStyle(ChatFormatting.GRAY)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasTarget(stack)) {
|
if (hasTarget(stack)) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Target: ")
|
Component.translatable("item.tiedup.key.target", getTargetName(stack))
|
||||||
.withStyle(ChatFormatting.BLUE)
|
.withStyle(ChatFormatting.BLUE)
|
||||||
.append(
|
|
||||||
Component.literal(getTargetName(stack)).withStyle(
|
|
||||||
ChatFormatting.WHITE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Right-click a collared player to toggle LOCK")
|
Component.translatable("item.tiedup.key.hint")
|
||||||
.withStyle(ChatFormatting.DARK_GRAY)
|
.withStyle(ChatFormatting.DARK_GRAY)
|
||||||
.withStyle(ChatFormatting.ITALIC)
|
.withStyle(ChatFormatting.ITALIC)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -63,16 +63,15 @@ public class ItemLockpick extends Item {
|
|||||||
|
|
||||||
int remaining = stack.getMaxDamage() - stack.getDamageValue();
|
int remaining = stack.getMaxDamage() - stack.getDamageValue();
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal(
|
Component.translatable("item.tiedup.lockpick.uses", remaining, stack.getMaxDamage())
|
||||||
"Uses: " + remaining + "/" + stack.getMaxDamage()
|
.withStyle(ChatFormatting.DARK_GRAY)
|
||||||
).withStyle(ChatFormatting.DARK_GRAY)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// LOW FIX: Removed server config access from client tooltip (desync issue)
|
// LOW FIX: Removed server config access from client tooltip (desync issue)
|
||||||
// Success/break chances depend on server config, not client config
|
// Success/break chances depend on server config, not client config
|
||||||
// Displaying client config values here would be misleading in multiplayer
|
// Displaying client config values here would be misleading in multiplayer
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Success/break chances: Check server config")
|
Component.translatable("item.tiedup.lockpick.chances_hint")
|
||||||
.withStyle(ChatFormatting.GRAY)
|
.withStyle(ChatFormatting.GRAY)
|
||||||
.withStyle(ChatFormatting.ITALIC)
|
.withStyle(ChatFormatting.ITALIC)
|
||||||
);
|
);
|
||||||
@@ -354,11 +353,11 @@ public class ItemLockpick extends Item {
|
|||||||
) {
|
) {
|
||||||
if (player.getServer() == null) return;
|
if (player.getServer() == null) return;
|
||||||
|
|
||||||
Component warning = Component.literal("ALERT: ")
|
Component warning = Component.translatable("item.tiedup.lockpick.alert_prefix")
|
||||||
.withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
.withStyle(ChatFormatting.RED, ChatFormatting.BOLD)
|
||||||
.append(
|
.append(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
player.getName().getString() + " tried to pick a lock!"
|
"item.tiedup.lockpick.alert_attempt", player.getName().getString()
|
||||||
).withStyle(ChatFormatting.GOLD)
|
).withStyle(ChatFormatting.GOLD)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -60,20 +60,17 @@ public class ItemRag extends Item {
|
|||||||
int ticksRemaining = getWetTime(stack);
|
int ticksRemaining = getWetTime(stack);
|
||||||
int secondsRemaining = ticksRemaining / 20;
|
int secondsRemaining = ticksRemaining / 20;
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Soaked with chloroform").withStyle(
|
Component.translatable("item.tiedup.rag.soaked")
|
||||||
ChatFormatting.GREEN
|
.withStyle(ChatFormatting.GREEN)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal(
|
Component.translatable("item.tiedup.rag.evaporates", secondsRemaining)
|
||||||
"Evaporates in: " + secondsRemaining + "s"
|
.withStyle(ChatFormatting.GRAY)
|
||||||
).withStyle(ChatFormatting.GRAY)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Dry - needs chloroform").withStyle(
|
Component.translatable("item.tiedup.rag.dry")
|
||||||
ChatFormatting.GRAY
|
.withStyle(ChatFormatting.GRAY)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,20 +47,18 @@ public class ItemShockerController extends ItemOwnerTarget {
|
|||||||
|
|
||||||
if (isBroadcastEnabled(stack)) {
|
if (isBroadcastEnabled(stack)) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("MODE: BROADCAST").withStyle(
|
Component.translatable("item.tiedup.shocker.mode_broadcast")
|
||||||
ChatFormatting.DARK_RED
|
.withStyle(ChatFormatting.DARK_RED)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("(Affects ALL your slaves in radius)")
|
Component.translatable("item.tiedup.shocker.broadcast_desc")
|
||||||
.withStyle(ChatFormatting.GRAY)
|
.withStyle(ChatFormatting.GRAY)
|
||||||
.withStyle(ChatFormatting.ITALIC)
|
.withStyle(ChatFormatting.ITALIC)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("MODE: TARGETED").withStyle(
|
Component.translatable("item.tiedup.shocker.mode_targeted")
|
||||||
ChatFormatting.BLUE
|
.withStyle(ChatFormatting.BLUE)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
if (hasTarget(stack)) {
|
if (hasTarget(stack)) {
|
||||||
String displayName = getTargetName(stack);
|
String displayName = getTargetName(stack);
|
||||||
@@ -102,7 +100,7 @@ public class ItemShockerController extends ItemOwnerTarget {
|
|||||||
|
|
||||||
if (isDisconnected) {
|
if (isDisconnected) {
|
||||||
targetComp.append(
|
targetComp.append(
|
||||||
Component.literal(" [FREED]")
|
Component.translatable("item.tiedup.shocker.freed")
|
||||||
.withStyle(ChatFormatting.RED)
|
.withStyle(ChatFormatting.RED)
|
||||||
.withStyle(ChatFormatting.BOLD)
|
.withStyle(ChatFormatting.BOLD)
|
||||||
);
|
);
|
||||||
@@ -110,20 +108,18 @@ public class ItemShockerController extends ItemOwnerTarget {
|
|||||||
tooltip.add(targetComp);
|
tooltip.add(targetComp);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal(" > No target connected").withStyle(
|
Component.translatable("item.tiedup.shocker.no_target")
|
||||||
ChatFormatting.GRAY
|
.withStyle(ChatFormatting.GRAY)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Radius: " + getRadius(stack) + "m").withStyle(
|
Component.translatable("item.tiedup.shocker.radius", getRadius(stack))
|
||||||
ChatFormatting.GREEN
|
.withStyle(ChatFormatting.GREEN)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Shift + Right-click to toggle Broadcast mode")
|
Component.translatable("item.tiedup.shocker.hint")
|
||||||
.withStyle(ChatFormatting.DARK_GRAY)
|
.withStyle(ChatFormatting.DARK_GRAY)
|
||||||
.withStyle(ChatFormatting.ITALIC)
|
.withStyle(ChatFormatting.ITALIC)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.tiedup.remake.items;
|
package com.tiedup.remake.items;
|
||||||
|
|
||||||
import com.tiedup.remake.core.TiedUpMod;
|
import com.tiedup.remake.core.TiedUpMod;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@@ -38,9 +39,8 @@ public class ItemTiedUpGuide extends Item {
|
|||||||
// Check if Patchouli is installed
|
// Check if Patchouli is installed
|
||||||
if (!ModList.get().isLoaded("patchouli")) {
|
if (!ModList.get().isLoaded("patchouli")) {
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable("item.tiedup.guide.no_patchouli")
|
||||||
"§cPatchouli is not installed! Install it to use this guide."
|
.withStyle(ChatFormatting.RED),
|
||||||
),
|
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
return InteractionResultHolder.fail(stack);
|
return InteractionResultHolder.fail(stack);
|
||||||
@@ -52,9 +52,8 @@ public class ItemTiedUpGuide extends Item {
|
|||||||
);
|
);
|
||||||
if (guideBookItem == null) {
|
if (guideBookItem == null) {
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable("item.tiedup.guide.book_not_found")
|
||||||
"§cFailed to find Patchouli guide_book item."
|
.withStyle(ChatFormatting.RED),
|
||||||
),
|
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
return InteractionResultHolder.fail(stack);
|
return InteractionResultHolder.fail(stack);
|
||||||
@@ -76,7 +75,8 @@ public class ItemTiedUpGuide extends Item {
|
|||||||
stack.shrink(1);
|
stack.shrink(1);
|
||||||
|
|
||||||
player.displayClientMessage(
|
player.displayClientMessage(
|
||||||
Component.literal("§aReceived TiedUp! Guide Book!"),
|
Component.translatable("item.tiedup.guide.received")
|
||||||
|
.withStyle(ChatFormatting.GREEN),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,25 +39,25 @@ public class ItemToken extends Item {
|
|||||||
TooltipFlag flag
|
TooltipFlag flag
|
||||||
) {
|
) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Camp Access Token").withStyle(
|
Component.translatable("item.tiedup.token.title").withStyle(
|
||||||
ChatFormatting.GOLD,
|
ChatFormatting.GOLD,
|
||||||
ChatFormatting.BOLD
|
ChatFormatting.BOLD
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
tooltip.add(Component.literal(""));
|
tooltip.add(Component.literal(""));
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Kidnappers won't target you").withStyle(
|
Component.translatable("item.tiedup.token.effect_no_target").withStyle(
|
||||||
ChatFormatting.GREEN
|
ChatFormatting.GREEN
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Allows trading with Slave Traders").withStyle(
|
Component.translatable("item.tiedup.token.effect_trading").withStyle(
|
||||||
ChatFormatting.GREEN
|
ChatFormatting.GREEN
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
tooltip.add(Component.literal(""));
|
tooltip.add(Component.literal(""));
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Keep in your inventory for effect").withStyle(
|
Component.translatable("item.tiedup.token.hint").withStyle(
|
||||||
ChatFormatting.GRAY,
|
ChatFormatting.GRAY,
|
||||||
ChatFormatting.ITALIC
|
ChatFormatting.ITALIC
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ public abstract class ItemOwnerTarget extends Item {
|
|||||||
) {
|
) {
|
||||||
if (hasOwner(stack)) {
|
if (hasOwner(stack)) {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal("Owner: ")
|
Component.translatable("item.tiedup.owner_target.owner")
|
||||||
.withStyle(ChatFormatting.GOLD)
|
.withStyle(ChatFormatting.GOLD)
|
||||||
.append(
|
.append(
|
||||||
Component.literal(getOwnerName(stack)).withStyle(
|
Component.literal(getOwnerName(stack)).withStyle(
|
||||||
@@ -167,8 +167,8 @@ public abstract class ItemOwnerTarget extends Item {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
tooltip.add(
|
tooltip.add(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Unclaimed (" + unclaimedHint + ")"
|
"item.tiedup.owner_target.unclaimed", unclaimedHint
|
||||||
).withStyle(ChatFormatting.GRAY)
|
).withStyle(ChatFormatting.GRAY)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.tiedup.remake.items.bondage3d;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for items that have a 3D model configuration.
|
|
||||||
* Implement this to provide custom position, scale, and rotation for 3D rendering.
|
|
||||||
*/
|
|
||||||
public interface IHas3DModelConfig {
|
|
||||||
/**
|
|
||||||
* Get the 3D model configuration for rendering.
|
|
||||||
* @return The Model3DConfig with position, scale, and rotation offsets
|
|
||||||
*/
|
|
||||||
Model3DConfig getModelConfig();
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package com.tiedup.remake.items.bondage3d;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration immutable for a 3D item.
|
|
||||||
* Contains all parameters necessary for rendering.
|
|
||||||
*/
|
|
||||||
public record Model3DConfig(
|
|
||||||
String objPath, // "tiedup:models/obj/ball_gag/model.obj"
|
|
||||||
String texturePath, // "tiedup:models/obj/ball_gag/texture.png" (or null = use MTL)
|
|
||||||
float posOffsetX, // Horizontal offset
|
|
||||||
float posOffsetY, // Vertical offset (negative = lower)
|
|
||||||
float posOffsetZ, // Depth offset (positive = forward)
|
|
||||||
float scale, // Scale (1.0 = normal size)
|
|
||||||
float rotOffsetX, // Additional X rotation
|
|
||||||
float rotOffsetY, // Additional Y rotation
|
|
||||||
float rotOffsetZ, // Additional Z rotation
|
|
||||||
Set<String> tintMaterials // Material names to apply color tint (e.g., "Ball")
|
|
||||||
) {
|
|
||||||
/** Config without tinting */
|
|
||||||
public static Model3DConfig simple(String objPath, String texturePath) {
|
|
||||||
return new Model3DConfig(
|
|
||||||
objPath,
|
|
||||||
texturePath,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1.0f,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
Set.of()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Config with position/rotation but no tinting */
|
|
||||||
public Model3DConfig(
|
|
||||||
String objPath,
|
|
||||||
String texturePath,
|
|
||||||
float posOffsetX,
|
|
||||||
float posOffsetY,
|
|
||||||
float posOffsetZ,
|
|
||||||
float scale,
|
|
||||||
float rotOffsetX,
|
|
||||||
float rotOffsetY,
|
|
||||||
float rotOffsetZ
|
|
||||||
) {
|
|
||||||
this(
|
|
||||||
objPath,
|
|
||||||
texturePath,
|
|
||||||
posOffsetX,
|
|
||||||
posOffsetY,
|
|
||||||
posOffsetZ,
|
|
||||||
scale,
|
|
||||||
rotOffsetX,
|
|
||||||
rotOffsetY,
|
|
||||||
rotOffsetZ,
|
|
||||||
Set.of()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check if this item supports color tinting */
|
|
||||||
public boolean supportsTinting() {
|
|
||||||
return tintMaterials != null && !tintMaterials.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -46,8 +46,8 @@ public class StruggleSessionManager {
|
|||||||
> continuousSessions = new ConcurrentHashMap<>();
|
> continuousSessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping from legacy V1 slot indices to V2 BodyRegionV2.
|
* Mapping from legacy slot indices to V2 BodyRegionV2.
|
||||||
* Used to convert V1 session targetSlot ordinals to V2 regions.
|
* Used to convert legacy session targetSlot ordinals to V2 regions.
|
||||||
* Index: 0=ARMS, 1=MOUTH, 2=EYES, 3=EARS, 4=NECK, 5=TORSO, 6=HANDS.
|
* Index: 0=ARMS, 1=MOUTH, 2=EYES, 3=EARS, 4=NECK, 5=TORSO, 6=HANDS.
|
||||||
*/
|
*/
|
||||||
private static final BodyRegionV2[] SLOT_TO_REGION = {
|
private static final BodyRegionV2[] SLOT_TO_REGION = {
|
||||||
@@ -83,16 +83,16 @@ public class StruggleSessionManager {
|
|||||||
) {
|
) {
|
||||||
UUID playerId = player.getUUID();
|
UUID playerId = player.getUUID();
|
||||||
|
|
||||||
// Remove any existing continuous session
|
// RISK-002 fix: reject if active session exists (prevents direction re-roll exploit)
|
||||||
ContinuousStruggleMiniGameState existing = continuousSessions.get(
|
ContinuousStruggleMiniGameState existing = continuousSessions.get(
|
||||||
playerId
|
playerId
|
||||||
);
|
);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
TiedUpMod.LOGGER.debug(
|
TiedUpMod.LOGGER.debug(
|
||||||
"[StruggleSessionManager] Replacing existing continuous struggle session for {}",
|
"[StruggleSessionManager] Rejected continuous session: active session already exists for {}",
|
||||||
player.getName().getString()
|
player.getName().getString()
|
||||||
);
|
);
|
||||||
continuousSessions.remove(playerId);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new session with configurable rate
|
// Create new session with configurable rate
|
||||||
@@ -146,12 +146,16 @@ public class StruggleSessionManager {
|
|||||||
) {
|
) {
|
||||||
UUID playerId = player.getUUID();
|
UUID playerId = player.getUUID();
|
||||||
|
|
||||||
// Remove any existing session
|
// RISK-002 fix: reject if active session exists (prevents direction re-roll exploit)
|
||||||
ContinuousStruggleMiniGameState existing = continuousSessions.get(
|
ContinuousStruggleMiniGameState existing = continuousSessions.get(
|
||||||
playerId
|
playerId
|
||||||
);
|
);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
continuousSessions.remove(playerId);
|
TiedUpMod.LOGGER.debug(
|
||||||
|
"[StruggleSessionManager] Rejected accessory session: active session already exists for {}",
|
||||||
|
player.getName().getString()
|
||||||
|
);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new session with target slot and configurable rate
|
// Create new session with target slot and configurable rate
|
||||||
@@ -607,7 +611,7 @@ public class StruggleSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (session.isAccessoryStruggle()) {
|
if (session.isAccessoryStruggle()) {
|
||||||
// Handle accessory resistance update (V1 path -- slot index is legacy ordinal)
|
// Handle accessory resistance update (legacy slot-index path)
|
||||||
Integer slotIndex = session.getTargetSlot();
|
Integer slotIndex = session.getTargetSlot();
|
||||||
if (
|
if (
|
||||||
slotIndex == null ||
|
slotIndex == null ||
|
||||||
@@ -676,7 +680,7 @@ public class StruggleSessionManager {
|
|||||||
if (session.isV2Struggle()) {
|
if (session.isV2Struggle()) {
|
||||||
com.tiedup.remake.v2.BodyRegionV2 region =
|
com.tiedup.remake.v2.BodyRegionV2 region =
|
||||||
session.getTargetRegion();
|
session.getTargetRegion();
|
||||||
// BUG-001 fix: break lock before unequip (consistent with V1 accessory escape)
|
// BUG-001 fix: break lock before unequip (consistent with legacy accessory escape)
|
||||||
ItemStack stackInRegion =
|
ItemStack stackInRegion =
|
||||||
com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.getInRegion(
|
com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.getInRegion(
|
||||||
player,
|
player,
|
||||||
@@ -714,7 +718,7 @@ public class StruggleSessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Handle accessory escape (V1 path -- slot index is legacy ordinal)
|
// Handle accessory escape (legacy slot-index path)
|
||||||
Integer slotIndex = session.getTargetSlot();
|
Integer slotIndex = session.getTargetSlot();
|
||||||
if (
|
if (
|
||||||
slotIndex != null &&
|
slotIndex != null &&
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ import net.minecraftforge.network.simple.SimpleChannel;
|
|||||||
*/
|
*/
|
||||||
public class ModNetwork {
|
public class ModNetwork {
|
||||||
|
|
||||||
private static final String PROTOCOL_VERSION = "1";
|
private static final String PROTOCOL_VERSION = "2";
|
||||||
|
|
||||||
public static final SimpleChannel CHANNEL =
|
public static final SimpleChannel CHANNEL =
|
||||||
NetworkRegistry.newSimpleChannel(
|
NetworkRegistry.newSimpleChannel(
|
||||||
|
|||||||
@@ -345,8 +345,8 @@ public class PacketLockpickAttempt {
|
|||||||
jammed = true;
|
jammed = true;
|
||||||
|
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"The lock jammed! Only struggle can open it now."
|
"msg.tiedup.network.lock_jammed"
|
||||||
).withStyle(ChatFormatting.RED)
|
).withStyle(ChatFormatting.RED)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class PacketSlaveBeingFreed {
|
|||||||
// Build alert message
|
// Build alert message
|
||||||
Component message = Component.literal("")
|
Component message = Component.literal("")
|
||||||
.append(
|
.append(
|
||||||
Component.literal("[WARNING] ").withStyle(
|
Component.translatable("msg.tiedup.network.warning_prefix").withStyle(
|
||||||
ChatFormatting.RED,
|
ChatFormatting.RED,
|
||||||
ChatFormatting.BOLD
|
ChatFormatting.BOLD
|
||||||
)
|
)
|
||||||
@@ -96,14 +96,18 @@ public class PacketSlaveBeingFreed {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
Component.literal(" is trying to free ").withStyle(
|
Component.translatable("msg.tiedup.network.is_trying_to_free").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
Component.literal(slaveName).withStyle(ChatFormatting.YELLOW)
|
Component.literal(slaveName).withStyle(ChatFormatting.YELLOW)
|
||||||
)
|
)
|
||||||
.append(Component.literal(" at ").withStyle(ChatFormatting.RED))
|
.append(
|
||||||
|
Component.translatable("msg.tiedup.network.at_location").withStyle(
|
||||||
|
ChatFormatting.RED
|
||||||
|
)
|
||||||
|
)
|
||||||
.append(
|
.append(
|
||||||
Component.literal(
|
Component.literal(
|
||||||
"[" + x + ", " + y + ", " + z + "]"
|
"[" + x + ", " + y + ", " + z + "]"
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class PacketBuyCaptive {
|
|||||||
Entity traderEntity = level.getEntity(traderEntityId);
|
Entity traderEntity = level.getEntity(traderEntityId);
|
||||||
if (!(traderEntity instanceof EntitySlaveTrader trader)) {
|
if (!(traderEntity instanceof EntitySlaveTrader trader)) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal("Trader not found.").withStyle(
|
Component.translatable("msg.tiedup.network.trader_not_found").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -92,7 +92,7 @@ public class PacketBuyCaptive {
|
|||||||
// Verify player has token
|
// Verify player has token
|
||||||
if (!EntityKidnapper.hasTokenInInventory(buyer)) {
|
if (!EntityKidnapper.hasTokenInInventory(buyer)) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal("You need a token to trade.").withStyle(
|
Component.translatable("msg.tiedup.network.need_token").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -103,7 +103,7 @@ public class PacketBuyCaptive {
|
|||||||
UUID campId = trader.getCampUUID();
|
UUID campId = trader.getCampUUID();
|
||||||
if (campId == null) {
|
if (campId == null) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal("This trader has no camp.").withStyle(
|
Component.translatable("msg.tiedup.network.trader_no_camp").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -114,7 +114,7 @@ public class PacketBuyCaptive {
|
|||||||
CampOwnership.CampData campData = ownership.getCamp(campId);
|
CampOwnership.CampData campData = ownership.getCamp(campId);
|
||||||
if (campData == null) {
|
if (campData == null) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal("Camp not found.").withStyle(
|
Component.translatable("msg.tiedup.network.camp_not_found").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -137,7 +137,7 @@ public class PacketBuyCaptive {
|
|||||||
|
|
||||||
if (targetCell == null) {
|
if (targetCell == null) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal("Captive not found in camp.").withStyle(
|
Component.translatable("msg.tiedup.network.captive_not_in_camp").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -170,7 +170,7 @@ public class PacketBuyCaptive {
|
|||||||
|
|
||||||
if (kidnappedState == null || !kidnappedState.isForSell()) {
|
if (kidnappedState == null || !kidnappedState.isForSell()) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal("This captive is not for sale.").withStyle(
|
Component.translatable("msg.tiedup.network.captive_not_for_sale").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -181,7 +181,7 @@ public class PacketBuyCaptive {
|
|||||||
ItemTask price = kidnappedState.getSalePrice();
|
ItemTask price = kidnappedState.getSalePrice();
|
||||||
if (price == null) {
|
if (price == null) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal("Price not set for this captive.").withStyle(
|
Component.translatable("msg.tiedup.network.price_not_set").withStyle(
|
||||||
ChatFormatting.RED
|
ChatFormatting.RED
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -194,14 +194,11 @@ public class PacketBuyCaptive {
|
|||||||
|
|
||||||
if (available < required) {
|
if (available < required) {
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You need " +
|
"msg.tiedup.network.not_enough_items",
|
||||||
required +
|
required,
|
||||||
"x " +
|
price.getItem().getDescription().getString(),
|
||||||
price.getItem().getDescription().getString() +
|
available
|
||||||
" (have " +
|
|
||||||
available +
|
|
||||||
")"
|
|
||||||
).withStyle(ChatFormatting.RED)
|
).withStyle(ChatFormatting.RED)
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -229,8 +226,8 @@ public class PacketBuyCaptive {
|
|||||||
);
|
);
|
||||||
|
|
||||||
buyer.sendSystemMessage(
|
buyer.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Purchase complete! The maid will deliver your captive."
|
"msg.tiedup.network.purchase_maid_delivery"
|
||||||
).withStyle(ChatFormatting.GREEN)
|
).withStyle(ChatFormatting.GREEN)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public enum ToolMode {
|
|||||||
/** AxeItem - chop wood near master */
|
/** AxeItem - chop wood near master */
|
||||||
WOODCUTTING,
|
WOODCUTTING,
|
||||||
|
|
||||||
/** IBondageItem (BIND type) - capture untied damsels */
|
/** ARMS-region bondage item - capture untied damsels */
|
||||||
CAPTURE;
|
CAPTURE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -893,8 +893,8 @@ public class PrisonerService {
|
|||||||
) guardEntity.discard();
|
) guardEntity.discard();
|
||||||
}
|
}
|
||||||
player.sendSystemMessage(
|
player.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You have been returned to your cell."
|
"msg.tiedup.prison.returned_to_cell"
|
||||||
).withStyle(ChatFormatting.GRAY)
|
).withStyle(ChatFormatting.GRAY)
|
||||||
);
|
);
|
||||||
TiedUpMod.LOGGER.info(
|
TiedUpMod.LOGGER.info(
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ public interface IBondageState extends ICapturable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if gag item has gagging sound effect.
|
* Check if gag item has gagging sound effect.
|
||||||
* @return true if gag implements ItemGaggingEffect
|
* @return true if gag has a GaggingComponent
|
||||||
*/
|
*/
|
||||||
boolean hasGaggingEffect();
|
boolean hasGaggingEffect();
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import net.minecraft.world.item.ItemStack;
|
|||||||
* Risk: MEDIUM (core equipment system)
|
* Risk: MEDIUM (core equipment system)
|
||||||
*
|
*
|
||||||
* Epic 5F: Uses V2EquipmentHelper.
|
* Epic 5F: Uses V2EquipmentHelper.
|
||||||
* Uses low-level setInRegion for equips because V1 items (IBondageItem) do not
|
* Uses low-level setInRegion for equips because force-equip paths (commands, NPC AI,
|
||||||
* implement IV2BondageItem, so V2EquipmentHelper.equipItem() would reject them.
|
* NBT restore) should bypass V2EquipmentManager conflict resolution.
|
||||||
*/
|
*/
|
||||||
public class PlayerEquipment {
|
public class PlayerEquipment {
|
||||||
|
|
||||||
@@ -423,8 +423,12 @@ public class PlayerEquipment {
|
|||||||
// ========== Low-level V2 equipment operations ==========
|
// ========== Low-level V2 equipment operations ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Low-level equip: writes to V2 capability, calls IBondageItem lifecycle hooks, syncs.
|
* Low-level equip: writes to V2 capability, calls IV2BondageItem lifecycle hooks, syncs.
|
||||||
* Uses setInRegion directly because V1 items do not implement IV2BondageItem.
|
*
|
||||||
|
* <p>INTENTIONALLY bypasses V2EquipmentManager.tryEquip() because all callers
|
||||||
|
* (commands, NPC AI, NBT restore) are force-equip paths that should not be subject
|
||||||
|
* to V2 conflict resolution (SMELL-003 reviewed — bypass is by design).
|
||||||
|
* <p>Basic safety (isRegionOccupied, canEquip) is still checked here.</p>
|
||||||
*/
|
*/
|
||||||
private void equipInRegion(BodyRegionV2 region, ItemStack stack) {
|
private void equipInRegion(BodyRegionV2 region, ItemStack stack) {
|
||||||
Player player = host.getPlayer();
|
Player player = host.getPlayer();
|
||||||
@@ -437,7 +441,7 @@ public class PlayerEquipment {
|
|||||||
// Check if already occupied
|
// Check if already occupied
|
||||||
if (equip.isRegionOccupied(region)) return;
|
if (equip.isRegionOccupied(region)) return;
|
||||||
|
|
||||||
// Check canEquip via V1 IBondageItem interface
|
// Check canEquip via IV2BondageItem interface
|
||||||
if (stack.getItem() instanceof IV2BondageItem bondageItem) {
|
if (stack.getItem() instanceof IV2BondageItem bondageItem) {
|
||||||
if (!bondageItem.canEquip(stack, player)) return;
|
if (!bondageItem.canEquip(stack, player)) return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,8 +141,8 @@ public class ForceFeedingTask extends TimedInteractTask {
|
|||||||
|
|
||||||
if (feeder instanceof ServerPlayer serverFeeder) {
|
if (feeder instanceof ServerPlayer serverFeeder) {
|
||||||
serverFeeder.displayClientMessage(
|
serverFeeder.displayClientMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"You force fed " + targetName + "."
|
"msg.tiedup.forcefeeding.you_fed", targetName
|
||||||
).withStyle(ChatFormatting.GRAY),
|
).withStyle(ChatFormatting.GRAY),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
@@ -150,9 +150,8 @@ public class ForceFeedingTask extends TimedInteractTask {
|
|||||||
|
|
||||||
if (targetEntity instanceof ServerPlayer serverTarget) {
|
if (targetEntity instanceof ServerPlayer serverTarget) {
|
||||||
serverTarget.displayClientMessage(
|
serverTarget.displayClientMessage(
|
||||||
Component.literal("You have been force fed.").withStyle(
|
Component.translatable("msg.tiedup.forcefeeding.been_fed")
|
||||||
ChatFormatting.GRAY
|
.withStyle(ChatFormatting.GRAY),
|
||||||
),
|
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public class TyingPlayerTask extends TyingTask {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send progress packets to both kidnapper and target (if players).
|
* Send progress packets to both kidnapper and target (if players).
|
||||||
* Called every tick from ItemBind or RestraintTaskTickHandler.
|
* Called every tick from RestraintTaskTickHandler.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void sendProgressPackets() {
|
public void sendProgressPackets() {
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
/**
|
/**
|
||||||
* Helper class for common bondage equipment interaction logic.
|
* Helper class for common bondage equipment interaction logic.
|
||||||
*
|
*
|
||||||
* This class extracts the duplicated interactLivingEntity pattern
|
* This class extracts the common interactLivingEntity pattern
|
||||||
* from ItemGag, ItemBlindfold, ItemMittens, ItemEarplugs, and ItemCollar.
|
* for bondage equipment items (gags, blindfolds, mittens, earplugs, collars).
|
||||||
*/
|
*/
|
||||||
public class EquipmentInteractionHelper {
|
public class EquipmentInteractionHelper {
|
||||||
|
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ public final class RestraintApplicator {
|
|||||||
// Notify the prisoner
|
// Notify the prisoner
|
||||||
if (prisoner instanceof ServerPlayer serverPlayer) {
|
if (prisoner instanceof ServerPlayer serverPlayer) {
|
||||||
serverPlayer.sendSystemMessage(
|
serverPlayer.sendSystemMessage(
|
||||||
Component.literal(
|
Component.translatable(
|
||||||
"Your restraints have been tightened!"
|
"msg.tiedup.restraint.tightened"
|
||||||
).withStyle(ChatFormatting.RED)
|
).withStyle(ChatFormatting.RED)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public final class BindModeHelper {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given stack is a bind item (V2 ARMS-region item or V1 ItemBind).
|
* Check if the given stack is a bind item (ARMS-region data-driven item).
|
||||||
*/
|
*/
|
||||||
public static boolean isBindItem(ItemStack stack) {
|
public static boolean isBindItem(ItemStack stack) {
|
||||||
if (stack.isEmpty()) return false;
|
if (stack.isEmpty()) return false;
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import net.minecraft.world.phys.AABB;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static utility for collar operations bridging V1 (ItemCollar subclasses)
|
* Static utility for collar operations using V2 data-driven items
|
||||||
* and V2 (data-driven items with OwnershipComponent).
|
* with OwnershipComponent.
|
||||||
*/
|
*/
|
||||||
public final class CollarHelper {
|
public final class CollarHelper {
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
|
|||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the {@link PoseType} for any bondage item stack (V1 or V2).
|
* Resolves the {@link PoseType} for any bondage item stack.
|
||||||
*
|
*
|
||||||
* <p>V2 items read from the data-driven definition's {@code pose_type} field.
|
* <p>Reads from the data-driven definition's {@code pose_type} field,
|
||||||
* V1 items fall back to {@code ItemBind.getPoseType()}.</p>
|
* falling back to {@link PoseType#STANDARD} if absent.</p>
|
||||||
*/
|
*/
|
||||||
public final class PoseTypeHelper {
|
public final class PoseTypeHelper {
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import net.minecraft.world.item.ItemStack;
|
|||||||
/**
|
/**
|
||||||
* Handles the tying interaction flow for V2 data-driven ARMS items.
|
* Handles the tying interaction flow for V2 data-driven ARMS items.
|
||||||
*
|
*
|
||||||
* <p>Extracted from {@code ItemBind.interactLivingEntity()} to support
|
* <p>Originally extracted from the former {@code ItemBind.interactLivingEntity()},
|
||||||
* the same tying task flow for data-driven items.</p>
|
* now the canonical tying flow for all data-driven ARMS items.</p>
|
||||||
*/
|
*/
|
||||||
public final class TyingInteractionHelper {
|
public final class TyingInteractionHelper {
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.tiedup.remake.v2.bondage;
|
package com.tiedup.remake.v2.bondage;
|
||||||
|
|
||||||
import com.tiedup.remake.core.TiedUpMod;
|
import com.tiedup.remake.core.TiedUpMod;
|
||||||
|
import com.tiedup.remake.items.base.ILockable;
|
||||||
import com.tiedup.remake.v2.BodyRegionV2;
|
import com.tiedup.remake.v2.BodyRegionV2;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
@@ -149,7 +150,14 @@ public final class V2EquipmentManager {
|
|||||||
return V2EquipResult.swapped(conflictStack);
|
return V2EquipResult.swapped(conflictStack);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Non-V2 item in region — log warning and remove
|
// Non-V2 item in region — RISK-003 fix: check if locked before removing
|
||||||
|
if (conflictStack.getItem() instanceof ILockable lockable && lockable.isLocked(conflictStack)) {
|
||||||
|
TiedUpMod.LOGGER.warn(
|
||||||
|
"V2EquipmentManager: blocked swap of locked non-V2 item {} from equipment",
|
||||||
|
conflictStack
|
||||||
|
);
|
||||||
|
return V2EquipResult.BLOCKED;
|
||||||
|
}
|
||||||
TiedUpMod.LOGGER.warn(
|
TiedUpMod.LOGGER.warn(
|
||||||
"V2EquipmentManager: swapping out non-V2 item {} from equipment",
|
"V2EquipmentManager: swapping out non-V2 item {} from equipment",
|
||||||
conflictStack
|
conflictStack
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
package com.tiedup.remake.v2.bondage.movement;
|
package com.tiedup.remake.v2.bondage.movement;
|
||||||
|
|
||||||
import com.tiedup.remake.items.base.PoseType;
|
|
||||||
import com.tiedup.remake.v2.bondage.BindModeHelper;
|
|
||||||
import com.tiedup.remake.v2.bondage.PoseTypeHelper;
|
|
||||||
import com.tiedup.remake.v2.BodyRegionV2;
|
import com.tiedup.remake.v2.BodyRegionV2;
|
||||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition;
|
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition;
|
||||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
|
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the winning movement style from a player's equipped bondage items.
|
* Resolves the winning movement style from a player's equipped bondage items.
|
||||||
@@ -18,32 +14,15 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
*
|
*
|
||||||
* <p>The winning item's {@link MovementModifier} (if present) overrides the style's
|
* <p>The winning item's {@link MovementModifier} (if present) overrides the style's
|
||||||
* default speed/jump values. Modifiers from lower-severity items are ignored.</p>
|
* default speed/jump values. Modifiers from lower-severity items are ignored.</p>
|
||||||
*
|
|
||||||
* <h3>V1 Compatibility (H6 fix)</h3>
|
|
||||||
* <p>V1 items (ItemBind) stored in V2 capability
|
|
||||||
* do not have data-driven definitions. This resolver provides a fallback that
|
|
||||||
* maps V1 bind mode + pose type to a {@link MovementStyle} with speed values matching
|
|
||||||
* the original V1 behavior, preventing double stacking between the legacy
|
|
||||||
* {@code RestraintEffectUtils} attribute modifier and the V2 modifier.</p>
|
|
||||||
*/
|
*/
|
||||||
public final class MovementStyleResolver {
|
public final class MovementStyleResolver {
|
||||||
|
|
||||||
private MovementStyleResolver() {}
|
private MovementStyleResolver() {}
|
||||||
|
|
||||||
// --- V1 fallback speed values ---
|
|
||||||
// V1 used ADDITION(-0.09) on base 0.10 = 0.01 effective = 10% speed
|
|
||||||
// Expressed as MULTIPLY_BASE fraction: 0.10
|
|
||||||
private static final float V1_STANDARD_SPEED = 0.10f;
|
|
||||||
|
|
||||||
// V1 used ADDITION(-0.10) on base 0.10 = 0.00 effective = 0% speed
|
|
||||||
// Expressed as MULTIPLY_BASE fraction: 0.0 (fully immobile)
|
|
||||||
private static final float V1_IMMOBILIZED_SPEED = 0.0f;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the winning movement style from all equipped items.
|
* Resolve the winning movement style from all equipped items.
|
||||||
*
|
*
|
||||||
* <p>Checks V2 data-driven definitions first, then falls back to V1 {@link ItemBind}
|
* <p>Uses V2 data-driven definitions to determine movement style.</p>
|
||||||
* introspection for items without data-driven definitions.</p>
|
|
||||||
*
|
*
|
||||||
* @param equipped map of region to ItemStack (from {@code IV2BondageEquipment.getAllEquipped()})
|
* @param equipped map of region to ItemStack (from {@code IV2BondageEquipment.getAllEquipped()})
|
||||||
* @return the resolved movement, or {@link ResolvedMovement#NONE} if no styled items
|
* @return the resolved movement, or {@link ResolvedMovement#NONE} if no styled items
|
||||||
@@ -66,7 +45,6 @@ public final class MovementStyleResolver {
|
|||||||
ItemStack stack = entry.getValue();
|
ItemStack stack = entry.getValue();
|
||||||
if (stack.isEmpty()) continue;
|
if (stack.isEmpty()) continue;
|
||||||
|
|
||||||
// --- Try V2 data-driven definition first ---
|
|
||||||
DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
|
DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
|
||||||
if (def != null && def.movementStyle() != null) {
|
if (def != null && def.movementStyle() != null) {
|
||||||
MovementStyle style = def.movementStyle();
|
MovementStyle style = def.movementStyle();
|
||||||
@@ -90,26 +68,6 @@ public final class MovementStyleResolver {
|
|||||||
bestSeverity = severity;
|
bestSeverity = severity;
|
||||||
bestRegionOrdinal = regionOrdinal;
|
bestRegionOrdinal = regionOrdinal;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- V1 fallback: ItemBind without data-driven definition ---
|
|
||||||
V1Fallback fallback = resolveV1Fallback(stack);
|
|
||||||
if (fallback != null) {
|
|
||||||
int severity = fallback.style.getSeverity();
|
|
||||||
int regionOrdinal = region.ordinal();
|
|
||||||
|
|
||||||
if (
|
|
||||||
severity > bestSeverity ||
|
|
||||||
(severity == bestSeverity &&
|
|
||||||
regionOrdinal < bestRegionOrdinal)
|
|
||||||
) {
|
|
||||||
bestStyle = fallback.style;
|
|
||||||
bestSpeed = fallback.speed;
|
|
||||||
bestJumpDisabled = fallback.jumpDisabled;
|
|
||||||
bestSeverity = severity;
|
|
||||||
bestRegionOrdinal = regionOrdinal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,56 +77,4 @@ public final class MovementStyleResolver {
|
|||||||
|
|
||||||
return new ResolvedMovement(bestStyle, bestSpeed, bestJumpDisabled);
|
return new ResolvedMovement(bestStyle, bestSpeed, bestJumpDisabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== V1 Fallback ====================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to derive a movement style from a V1 bind item.
|
|
||||||
*
|
|
||||||
* <p>Only items with legs bound produce a movement style. The mapping preserves
|
|
||||||
* the original V1 speed values:</p>
|
|
||||||
* <ul>
|
|
||||||
* <li>WRAP / LATEX_SACK: SHUFFLE at 0% speed (full immobilization), jump disabled</li>
|
|
||||||
* <li>DOG / HUMAN_CHAIR: CRAWL at V1 standard speed (10%), jump disabled</li>
|
|
||||||
* <li>STANDARD / STRAITJACKET: SHUFFLE at 10% speed, jump disabled</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param stack the ItemStack to inspect
|
|
||||||
* @return fallback resolution, or null if the item is not a V1 bind or legs are not bound
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private static V1Fallback resolveV1Fallback(ItemStack stack) {
|
|
||||||
if (!BindModeHelper.isBindItem(stack)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!BindModeHelper.hasLegsBound(stack)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
PoseType poseType = PoseTypeHelper.getPoseType(stack);
|
|
||||||
|
|
||||||
return switch (poseType) {
|
|
||||||
case WRAP, LATEX_SACK -> new V1Fallback(
|
|
||||||
MovementStyle.SHUFFLE,
|
|
||||||
V1_IMMOBILIZED_SPEED,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
case DOG, HUMAN_CHAIR -> new V1Fallback(
|
|
||||||
MovementStyle.CRAWL,
|
|
||||||
V1_STANDARD_SPEED,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
default ->
|
|
||||||
// STANDARD, STRAITJACKET: shuffle at V1 standard speed
|
|
||||||
new V1Fallback(MovementStyle.SHUFFLE, V1_STANDARD_SPEED, true);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Internal holder for V1 fallback resolution result. */
|
|
||||||
private record V1Fallback(
|
|
||||||
MovementStyle style,
|
|
||||||
float speed,
|
|
||||||
boolean jumpDisabled
|
|
||||||
) {}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,10 @@ public class PacketV2SelfLock {
|
|||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!PacketRateLimiter.allowPacket(player, "action")) return;
|
if (!PacketRateLimiter.allowPacket(player, "action")) return;
|
||||||
|
|
||||||
// Arms must be free to self-lock
|
// Arms and hands must be free to self-lock (RISK-006: mittens bypass)
|
||||||
if (
|
if (
|
||||||
V2EquipmentHelper.isRegionOccupied(player, BodyRegionV2.ARMS)
|
V2EquipmentHelper.isRegionOccupied(player, BodyRegionV2.ARMS) ||
|
||||||
|
V2EquipmentHelper.isRegionOccupied(player, BodyRegionV2.HANDS)
|
||||||
) return;
|
) return;
|
||||||
|
|
||||||
ItemStack equipped = V2EquipmentHelper.getInRegion(
|
ItemStack equipped = V2EquipmentHelper.getInRegion(
|
||||||
|
|||||||
@@ -42,9 +42,10 @@ public class PacketV2SelfUnlock {
|
|||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!PacketRateLimiter.allowPacket(player, "action")) return;
|
if (!PacketRateLimiter.allowPacket(player, "action")) return;
|
||||||
|
|
||||||
// Arms must be free to self-unlock
|
// Arms and hands must be free to self-unlock (RISK-006: mittens bypass)
|
||||||
if (
|
if (
|
||||||
V2EquipmentHelper.isRegionOccupied(player, BodyRegionV2.ARMS)
|
V2EquipmentHelper.isRegionOccupied(player, BodyRegionV2.ARMS) ||
|
||||||
|
V2EquipmentHelper.isRegionOccupied(player, BodyRegionV2.HANDS)
|
||||||
) return;
|
) return;
|
||||||
|
|
||||||
ItemStack equipped = V2EquipmentHelper.getInRegion(
|
ItemStack equipped = V2EquipmentHelper.getInRegion(
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ description='''${mod_description}'''
|
|||||||
[[mixins]]
|
[[mixins]]
|
||||||
config="tiedup.mixins.json"
|
config="tiedup.mixins.json"
|
||||||
|
|
||||||
|
[[mixins]]
|
||||||
|
config="tiedup-compat.mixins.json"
|
||||||
|
|
||||||
# Features are specific properties of the game environment, that you may want to declare you require. This example declares
|
# Features are specific properties of the game environment, that you may want to declare you require. This example declares
|
||||||
# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't
|
# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't
|
||||||
# stop your mod loading on the server for example.
|
# stop your mod loading on the server for example.
|
||||||
|
|||||||
@@ -263,6 +263,11 @@
|
|||||||
|
|
||||||
"gui.tiedup.merchant.title": "Merchant Trading",
|
"gui.tiedup.merchant.title": "Merchant Trading",
|
||||||
"gui.tiedup.merchant.buy": "Buy",
|
"gui.tiedup.merchant.buy": "Buy",
|
||||||
|
"gui.tiedup.merchant.your_gold": "Your Gold: ",
|
||||||
|
"gui.tiedup.merchant.gold_amount": "%sx ",
|
||||||
|
"gui.tiedup.merchant.gold_icon": "\u269c ",
|
||||||
|
"gui.tiedup.merchant.nugget_amount": "+ %sx ",
|
||||||
|
"gui.tiedup.merchant.nugget_icon": "\u2726",
|
||||||
|
|
||||||
"item.tiedup.clothes.tooltip.has_url": "Dynamic texture set",
|
"item.tiedup.clothes.tooltip.has_url": "Dynamic texture set",
|
||||||
"item.tiedup.clothes.tooltip.no_url": "No dynamic texture (use /tiedup clothes url set)",
|
"item.tiedup.clothes.tooltip.no_url": "No dynamic texture (use /tiedup clothes url set)",
|
||||||
@@ -297,6 +302,11 @@
|
|||||||
"gui.tiedup.command_wand.relationship": "Relationship",
|
"gui.tiedup.command_wand.relationship": "Relationship",
|
||||||
"gui.tiedup.command_wand.follow_distance.tooltip": "How closely the NPC follows. Click to cycle.",
|
"gui.tiedup.command_wand.follow_distance.tooltip": "How closely the NPC follows. Click to cycle.",
|
||||||
"gui.tiedup.command_wand.follow_distance.current": "Current",
|
"gui.tiedup.command_wand.follow_distance.current": "Current",
|
||||||
|
"gui.tiedup.command_wand.follow_distance.abbrev.heel": "H",
|
||||||
|
"gui.tiedup.command_wand.follow_distance.abbrev.close": "C",
|
||||||
|
"gui.tiedup.command_wand.follow_distance.abbrev.far": "F",
|
||||||
|
"gui.tiedup.command_wand.follow_distance.abbrev.unknown": "?",
|
||||||
|
"gui.tiedup.command_wand.percent": "%s%%",
|
||||||
"tiedup.follow_distance.far": "Far",
|
"tiedup.follow_distance.far": "Far",
|
||||||
"tiedup.follow_distance.close": "Close",
|
"tiedup.follow_distance.close": "Close",
|
||||||
"tiedup.follow_distance.heel": "Heel",
|
"tiedup.follow_distance.heel": "Heel",
|
||||||
@@ -306,6 +316,7 @@
|
|||||||
|
|
||||||
"gui.tiedup.npc_inventory": "NPC Inventory",
|
"gui.tiedup.npc_inventory": "NPC Inventory",
|
||||||
"gui.tiedup.npc_inventory.title": "Inventory",
|
"gui.tiedup.npc_inventory.title": "Inventory",
|
||||||
|
"gui.tiedup.npc_inventory.title_name": "%s's Inventory",
|
||||||
"gui.tiedup.npc_inventory.take_all": "Take All",
|
"gui.tiedup.npc_inventory.take_all": "Take All",
|
||||||
"gui.tiedup.equipment": "Equipment",
|
"gui.tiedup.equipment": "Equipment",
|
||||||
"gui.tiedup.equipment.short": "Gear",
|
"gui.tiedup.equipment.short": "Gear",
|
||||||
@@ -523,6 +534,12 @@
|
|||||||
"gui.tiedup.adjustment.no_gag": "No gag equipped",
|
"gui.tiedup.adjustment.no_gag": "No gag equipped",
|
||||||
"gui.tiedup.adjustment.no_blindfold": "No blindfold equipped",
|
"gui.tiedup.adjustment.no_blindfold": "No blindfold equipped",
|
||||||
"gui.tiedup.adjustment.both": "Adjusting both items",
|
"gui.tiedup.adjustment.both": "Adjusting both items",
|
||||||
|
"gui.tiedup.adjustment.btn.reset": "0",
|
||||||
|
"gui.tiedup.adjustment.btn.decrement": "-0.25",
|
||||||
|
"gui.tiedup.adjustment.btn.increment": "+0.25",
|
||||||
|
"gui.tiedup.adjustment.btn.scale_reset": "1x",
|
||||||
|
"gui.tiedup.adjustment.btn.scale_decrement": "-0.1",
|
||||||
|
"gui.tiedup.adjustment.btn.scale_increment": "+0.1",
|
||||||
|
|
||||||
"gui.tiedup.continuous_struggle.label.resistance": "RESISTANCE:",
|
"gui.tiedup.continuous_struggle.label.resistance": "RESISTANCE:",
|
||||||
"gui.tiedup.continuous_struggle.status.shocked": "SHOCKED!",
|
"gui.tiedup.continuous_struggle.status.shocked": "SHOCKED!",
|
||||||
@@ -560,6 +577,7 @@
|
|||||||
"gui.tiedup.cell_manager.label.op_mode": "(OP Mode)",
|
"gui.tiedup.cell_manager.label.op_mode": "(OP Mode)",
|
||||||
"gui.tiedup.cell_manager.label.owner": "Owner: %s",
|
"gui.tiedup.cell_manager.label.owner": "Owner: %s",
|
||||||
"gui.tiedup.cell_manager.label.empty": "(empty)",
|
"gui.tiedup.cell_manager.label.empty": "(empty)",
|
||||||
|
"gui.tiedup.cell_manager.tree_prefix": " \u2514\u2500 ",
|
||||||
"gui.tiedup.cell_manager.status.rename_hint": "Press Enter to save, Escape to cancel",
|
"gui.tiedup.cell_manager.status.rename_hint": "Press Enter to save, Escape to cancel",
|
||||||
"gui.tiedup.cell_manager.status.no_cells": "No cells created",
|
"gui.tiedup.cell_manager.status.no_cells": "No cells created",
|
||||||
"gui.tiedup.cell_manager.status.use_cellwand": "Use CellWand to create cells",
|
"gui.tiedup.cell_manager.status.use_cellwand": "Use CellWand to create cells",
|
||||||
@@ -651,6 +669,7 @@
|
|||||||
"gui.tiedup.tab.lower": "Lower",
|
"gui.tiedup.tab.lower": "Lower",
|
||||||
"gui.tiedup.tab.special": "Special",
|
"gui.tiedup.tab.special": "Special",
|
||||||
"gui.tiedup.tab_bar": "Tab bar, active: %s",
|
"gui.tiedup.tab_bar": "Tab bar, active: %s",
|
||||||
|
"gui.tiedup.tab_bar.label": "Tab Bar",
|
||||||
"gui.tiedup.equip": "+ Equip",
|
"gui.tiedup.equip": "+ Equip",
|
||||||
"gui.tiedup.close_esc": "Close [ESC]",
|
"gui.tiedup.close_esc": "Close [ESC]",
|
||||||
"gui.tiedup.action.equip": "Equip",
|
"gui.tiedup.action.equip": "Equip",
|
||||||
@@ -689,6 +708,7 @@
|
|||||||
"gui.tiedup.status.no_key": "No key",
|
"gui.tiedup.status.no_key": "No key",
|
||||||
"gui.tiedup.status.target_info": "Target: %s",
|
"gui.tiedup.status.target_info": "Target: %s",
|
||||||
"gui.tiedup.status_bar": "Status bar",
|
"gui.tiedup.status_bar": "Status bar",
|
||||||
|
"gui.tiedup.item_picker": "Item Picker",
|
||||||
|
|
||||||
"msg.tiedup.system.being_tied": "%1$s is tying you up!",
|
"msg.tiedup.system.being_tied": "%1$s is tying you up!",
|
||||||
"msg.tiedup.system.tied_up": "%1$s tied you up, you can't move!",
|
"msg.tiedup.system.tied_up": "%1$s tied you up, you can't move!",
|
||||||
@@ -963,5 +983,141 @@
|
|||||||
"command.tiedup.debt.set": "Set %1$s's total debt to %2$s emeralds.",
|
"command.tiedup.debt.set": "Set %1$s's total debt to %2$s emeralds.",
|
||||||
"command.tiedup.debt.added": "Added %1$s emeralds to %2$s's debt. Remaining: %3$s",
|
"command.tiedup.debt.added": "Added %1$s emeralds to %2$s's debt. Remaining: %3$s",
|
||||||
"command.tiedup.debt.removed": "Removed %1$s emeralds from %2$s's debt. Remaining: %3$s",
|
"command.tiedup.debt.removed": "Removed %1$s emeralds from %2$s's debt. Remaining: %3$s",
|
||||||
"command.tiedup.debt.removed_paid": "Removed %1$s emeralds from %2$s's debt. Remaining: %3$s (PAID OFF!)"
|
"command.tiedup.debt.removed_paid": "Removed %1$s emeralds from %2$s's debt. Remaining: %3$s (PAID OFF!)",
|
||||||
|
|
||||||
|
"item.tiedup.leather_mittens": "Leather Mittens",
|
||||||
|
"item.tiedup.ball_gag_3d": "Ball Gag",
|
||||||
|
"item.tiedup.taser": "Taser",
|
||||||
|
"item.tiedup.debug_wand": "Debug Wand",
|
||||||
|
|
||||||
|
"msg.tiedup.event.cant_drop_labor_tools": "You cannot drop labor tools!",
|
||||||
|
"msg.tiedup.event.cant_store_labor_tools": "You cannot store labor tools!",
|
||||||
|
"msg.tiedup.event.cant_eat_gagged": "You can't eat with a gag on.",
|
||||||
|
"msg.tiedup.event.death_escape": "You died and escaped captivity. Your items remain in the camp chest.",
|
||||||
|
"msg.tiedup.event.debt_increased": "Your debt has increased by %1$s emeralds for attacking %2$s!",
|
||||||
|
"msg.tiedup.event.task_failed": "Your task has been marked as failed. You will not be paid for your work.",
|
||||||
|
"msg.tiedup.event.returned_to_cell": "You have been returned to your cell for your insolence!",
|
||||||
|
"msg.tiedup.event.grace_lost": "You attacked a kidnapper - protection lost!",
|
||||||
|
"msg.tiedup.event.camp_defends_trader": "The camp defends their leader! You are now under attack!",
|
||||||
|
"msg.tiedup.event.camp_defends_maid": "The camp defends their servant! You are now under attack!",
|
||||||
|
"msg.tiedup.event.chest_locked_by_camp": "This chest is locked by the camp!",
|
||||||
|
"msg.tiedup.event.new_maid_arrived": "A new maid, %1$s, has arrived. Work resumes.",
|
||||||
|
|
||||||
|
"msg.tiedup.network.trader_not_found": "Trader not found.",
|
||||||
|
"msg.tiedup.network.need_token": "You need a token to trade.",
|
||||||
|
"msg.tiedup.network.trader_no_camp": "This trader has no camp.",
|
||||||
|
"msg.tiedup.network.camp_not_found": "Camp not found.",
|
||||||
|
"msg.tiedup.network.captive_not_in_camp": "Captive not found in camp.",
|
||||||
|
"msg.tiedup.network.captive_not_for_sale": "This captive is not for sale.",
|
||||||
|
"msg.tiedup.network.price_not_set": "Price not set for this captive.",
|
||||||
|
"msg.tiedup.network.not_enough_items": "You need %1$sx %2$s (have %3$s)",
|
||||||
|
"msg.tiedup.network.purchase_maid_delivery": "Purchase complete! The maid will deliver your captive.",
|
||||||
|
"msg.tiedup.network.lock_jammed": "The lock jammed! Only struggle can open it now.",
|
||||||
|
"msg.tiedup.network.warning_prefix": "[WARNING] ",
|
||||||
|
"msg.tiedup.network.is_trying_to_free": " is trying to free ",
|
||||||
|
"msg.tiedup.network.at_location": " at ",
|
||||||
|
|
||||||
|
"item.tiedup.owner_target.owner": "Owner: ",
|
||||||
|
"item.tiedup.owner_target.unclaimed": "Unclaimed (%1$s)",
|
||||||
|
"item.tiedup.key.owner": "Owner: %1$s",
|
||||||
|
"item.tiedup.key.unclaimed": "Unclaimed (Right-click a collar wearer to claim)",
|
||||||
|
"item.tiedup.key.target": "Target: %1$s",
|
||||||
|
"item.tiedup.key.hint": "Right-click a collared player to toggle LOCK",
|
||||||
|
"item.tiedup.shocker.mode_broadcast": "MODE: BROADCAST",
|
||||||
|
"item.tiedup.shocker.broadcast_desc": "(Affects ALL your slaves in radius)",
|
||||||
|
"item.tiedup.shocker.mode_targeted": "MODE: TARGETED",
|
||||||
|
"item.tiedup.shocker.freed": " [FREED]",
|
||||||
|
"item.tiedup.shocker.no_target": " > No target connected",
|
||||||
|
"item.tiedup.shocker.radius": "Radius: %1$sm",
|
||||||
|
"item.tiedup.shocker.hint": "Shift + Right-click to toggle Broadcast mode",
|
||||||
|
"item.tiedup.rag.soaked": "Soaked with chloroform",
|
||||||
|
"item.tiedup.rag.evaporates": "Evaporates in: %1$ss",
|
||||||
|
"item.tiedup.rag.dry": "Dry - needs chloroform",
|
||||||
|
"item.tiedup.gps_locator.target": "Target: %1$s",
|
||||||
|
"item.tiedup.lockpick.uses": "Uses: %1$s/%2$s",
|
||||||
|
"item.tiedup.lockpick.chances_hint": "Success/break chances: Check server config",
|
||||||
|
"item.tiedup.lockpick.alert_prefix": "ALERT: ",
|
||||||
|
"item.tiedup.lockpick.alert_attempt": "%1$s tried to pick a lock!",
|
||||||
|
"item.tiedup.token.title": "Camp Access Token",
|
||||||
|
"item.tiedup.token.effect_no_target": "Kidnappers won't target you",
|
||||||
|
"item.tiedup.token.effect_trading": "Allows trading with Slave Traders",
|
||||||
|
"item.tiedup.token.hint": "Keep in your inventory for effect",
|
||||||
|
"item.tiedup.cell_key.desc": "Unlocks any Iron Bar Door",
|
||||||
|
"item.tiedup.cell_key.restriction": "Does not work on bondage items",
|
||||||
|
"item.tiedup.guide.no_patchouli": "Patchouli is not installed! Install it to use this guide.",
|
||||||
|
"item.tiedup.guide.book_not_found": "Failed to find Patchouli guide_book item.",
|
||||||
|
"item.tiedup.guide.received": "Received TiedUp! Guide Book!",
|
||||||
|
"item.tiedup.knife.cutting_speed": "Cutting speed: %1$s res/s",
|
||||||
|
"item.tiedup.knife.cutting_time": "Cutting time: %1$ss (%2$s total res)",
|
||||||
|
"block.tiedup.trap.armed": "Armed",
|
||||||
|
"block.tiedup.trap.disarmed": "Disarmed",
|
||||||
|
"block.tiedup.kidnap_bomb.loaded": "Loaded:",
|
||||||
|
"block.tiedup.kidnap_bomb.empty": "Empty",
|
||||||
|
"msg.tiedup.bounty.broadcast": "[Bounty] %1$s",
|
||||||
|
"msg.tiedup.prison.returned_to_cell": "You have been returned to your cell.",
|
||||||
|
"msg.tiedup.forcefeeding.you_fed": "You force fed %1$s.",
|
||||||
|
"msg.tiedup.forcefeeding.been_fed": "You have been force fed.",
|
||||||
|
"msg.tiedup.restraint.tightened": "Your restraints have been tightened!",
|
||||||
|
"msg.tiedup.camp.captor_died": "Your captor has died. You are FREE!",
|
||||||
|
"msg.tiedup.camp.grace_period": "You have 5 minutes of protection from kidnappers.",
|
||||||
|
"msg.tiedup.petplay.cannot_eat_hand": "You cannot eat from your hand! Use a bowl.",
|
||||||
|
"msg.tiedup.petplay.cannot_sleep_bed": "You cannot sleep in a bed! Use your pet bed.",
|
||||||
|
"msg.tiedup.petplay.sleep_time_only": "You can only sleep at night or during thunderstorms.",
|
||||||
|
"msg.tiedup.petplay.curl_up_bed": "You curl up in your pet bed...",
|
||||||
|
|
||||||
|
"entity.tiedup.maid.died_work_paused": "The maid has died. Work is paused. A replacement will arrive in 5 minutes.",
|
||||||
|
"entity.tiedup.maid.manual_assign": "The maid manually assigns you to: %1$s",
|
||||||
|
"entity.tiedup.maid.collect_shortly": "A Maid will come to collect you shortly.",
|
||||||
|
"entity.tiedup.maid.labor_status_header": "=== Labor Status ===",
|
||||||
|
"entity.tiedup.maid.labor_status_state": "State: %1$s",
|
||||||
|
"entity.tiedup.maid.labor_status_task": "Task: %1$s",
|
||||||
|
"entity.tiedup.maid.labor_status_progress": "Progress: %1$s/%2$s",
|
||||||
|
"entity.tiedup.maid.labor_status_debt": "Remaining debt: %1$s emeralds",
|
||||||
|
"entity.tiedup.maid.labor_hint_start_task": "Shift+Right-Click to manually start task",
|
||||||
|
"entity.tiedup.maid.labor_hint_turn_in": "Shift+Right-Click to manually turn in task",
|
||||||
|
"entity.tiedup.master.caught_escaping": "%1$s caught you trying to escape!",
|
||||||
|
"entity.tiedup.master.pet_freed": "You are free! Your master %1$s is gone.",
|
||||||
|
"entity.tiedup.trader.no_token_warning": "You don't have a trader token. Leave now, or I'll make you leave.",
|
||||||
|
"entity.tiedup.trader.camp_destroyed": "A slave trader camp has been destroyed!",
|
||||||
|
"entity.tiedup.guard.attack_punished": "Attacking your guard is punished!",
|
||||||
|
"entity.tiedup.guard.eliminated_free": "Your guard has been eliminated! You are free!",
|
||||||
|
"entity.tiedup.damsel.needs_collar_to_feed": "This NPC needs a collar before you can feed them.",
|
||||||
|
"entity.tiedup.damsel.not_collar_owner": "You don't own this NPC's collar.",
|
||||||
|
"entity.tiedup.damsel.cant_eat_now": "This NPC can't eat that right now.",
|
||||||
|
"entity.tiedup.trade.price_both": "%1$s gold + %2$s nuggets",
|
||||||
|
"entity.tiedup.trade.price_gold": "%1$s gold",
|
||||||
|
"entity.tiedup.trade.price_nuggets": "%1$s nuggets",
|
||||||
|
"entity.tiedup.trade.price_free": "Free",
|
||||||
|
"entity.tiedup.pet.too_far_to_talk": "You are too far from your Master to talk.",
|
||||||
|
"entity.tiedup.pet.too_far_from_master": "You are too far from your Master.",
|
||||||
|
"entity.tiedup.pet.you_say": "You: %1$s",
|
||||||
|
"goal.tiedup.trader_sell.greeting": "[%1$s] %2$s",
|
||||||
|
"goal.tiedup.trader_sell.browse_hint": "Right-click me to browse my stock.",
|
||||||
|
"goal.tiedup.guard_monitor.too_far": "You are too far from your guard! Return within 15 seconds or escape will be triggered!",
|
||||||
|
"goal.tiedup.guard_monitor.returned": "You returned to your guard. Stay close!",
|
||||||
|
"goal.tiedup.maid_deliver.on_leash": "%1$s is now on your leash.",
|
||||||
|
"goal.tiedup.maid_deliver.delivered": "%1$s has been delivered to you.",
|
||||||
|
"goal.tiedup.guard_command.chasing": "%1$s is chasing %2$s!",
|
||||||
|
"goal.tiedup.guard_command.spotted": "%1$s spotted: %2$s!",
|
||||||
|
"goal.tiedup.maid_extract.extracted": "You have been extracted for labor. Complete your task: %1$s",
|
||||||
|
"goal.tiedup.master_watch.time_remaining": "%1$s - %2$ss remaining",
|
||||||
|
"goal.tiedup.master_watch.speak_waiting": "%1$s: \"I'm waiting...\"",
|
||||||
|
"goal.tiedup.master_watch.demand_warning": "%1$s: \"%2$s\"",
|
||||||
|
"goal.tiedup.master_watch.punishment": "%1$s: \"%2$s\"",
|
||||||
|
"goal.tiedup.master_inspect.confiscated": "%1$s confiscated %2$s contraband item(s) from you!",
|
||||||
|
"goal.tiedup.master_inspect.inspecting": "%1$s is inspecting your inventory...",
|
||||||
|
"goal.tiedup.master_assign.task_speech": "%1$s: \"%2$s\"",
|
||||||
|
"goal.tiedup.maid_idle.task_complete": "Task complete! Walk back to camp.",
|
||||||
|
"goal.tiedup.maid_idle.task_failed": "Task failed due to inactivity! You will be returned to your cell.",
|
||||||
|
"goal.tiedup.maid_idle.inactivity_warning": "Warning: Work or face punishment! (%1$s/3)",
|
||||||
|
"goal.tiedup.maid_assign.task_assigned": "Task assigned: %1$s",
|
||||||
|
"goal.tiedup.maid_assign.task_reward": "Reward: %1$s emeralds toward your debt.",
|
||||||
|
"goal.tiedup.maid.debt_paid_free": "Your debt is paid. You are FREE!",
|
||||||
|
"goal.tiedup.maid_init.imprisoned": "You have been imprisoned. Your debt: %1$s emeralds.",
|
||||||
|
"goal.tiedup.maid_init.confiscated": "Your valuables have been confiscated.",
|
||||||
|
"goal.tiedup.kidnapper_decide.still_tied": "You're still tied up - struggle to break free!",
|
||||||
|
"goal.tiedup.kidnapper_sale.tag": "[SALE] ",
|
||||||
|
"goal.tiedup.kidnapper_sale.is_selling": " is selling ",
|
||||||
|
"goal.tiedup.kidnapper_sale.for": " for ",
|
||||||
|
"goal.tiedup.kidnapper_sale.at": " at "
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "tiedup:item/debug_wand"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "tiedup:bondage_item",
|
"type": "tiedup:bondage_item",
|
||||||
"display_name": "Chains",
|
"display_name": "Chain",
|
||||||
"translation_key": "item.tiedup.chain",
|
"translation_key": "item.tiedup.chain",
|
||||||
"model": "tiedup:models/gltf/v2/binds/chain.glb",
|
"model": "tiedup:models/gltf/v2/binds/chain.glb",
|
||||||
"regions": [
|
"regions": [
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"components": {
|
"components": {
|
||||||
"lockable": {},
|
"lockable": {},
|
||||||
"resistance": {
|
"resistance": {
|
||||||
"id": "blindfold"
|
"id": "earplug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"body"
|
"body"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"display_name": "Auto Shock Collar",
|
"display_name": "Automatic Shock Collar",
|
||||||
"translation_key": "item.tiedup.shock_collar_auto",
|
"translation_key": "item.tiedup.shock_collar_auto",
|
||||||
"model": "tiedup:models/gltf/v2/collars/shock_collar_auto.glb",
|
"model": "tiedup:models/gltf/v2/collars/shock_collar_auto.glb",
|
||||||
"components": {
|
"components": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "tiedup:bondage_item",
|
"type": "tiedup:bondage_item",
|
||||||
"display_name": "Vine Bind",
|
"display_name": "Vine Seed",
|
||||||
"translation_key": "item.tiedup.vine_seed",
|
"translation_key": "item.tiedup.vine_seed",
|
||||||
"model": "tiedup:models/gltf/v2/binds/vine_seed.glb",
|
"model": "tiedup:models/gltf/v2/binds/vine_seed.glb",
|
||||||
"regions": [
|
"regions": [
|
||||||
|
|||||||
22
src/main/resources/tiedup-compat.mixins.json
Normal file
22
src/main/resources/tiedup-compat.mixins.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"required": false,
|
||||||
|
"minVersion": "0.8",
|
||||||
|
"package": "com.tiedup.remake.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_17",
|
||||||
|
"refmap": "tiedup.refmap.json",
|
||||||
|
"mixins": [
|
||||||
|
"MixinMCAVillagerInteraction",
|
||||||
|
"MixinMCAVillagerLeash",
|
||||||
|
"MixinMCAOpenAIChatAI",
|
||||||
|
"MixinMCAMessenger"
|
||||||
|
],
|
||||||
|
"client": [
|
||||||
|
"client/MixinVillagerEntityBaseModelMCA",
|
||||||
|
"client/MixinVillagerEntityMCAAnimated",
|
||||||
|
"client/MixinMCASpeechManager",
|
||||||
|
"client/MixinMCAPlayerExtendedModel"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,22 +6,14 @@
|
|||||||
"refmap": "tiedup.refmap.json",
|
"refmap": "tiedup.refmap.json",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"MixinServerPlayer",
|
"MixinServerPlayer",
|
||||||
"MixinMCAVillagerInteraction",
|
|
||||||
"MixinMCAVillagerLeash",
|
|
||||||
"MixinMCAOpenAIChatAI",
|
|
||||||
"MixinMCAMessenger",
|
|
||||||
"MixinLivingEntityBodyRot"
|
"MixinLivingEntityBodyRot"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"client/MixinVillagerEntityBaseModelMCA",
|
|
||||||
"client/MixinVillagerEntityMCAAnimated",
|
|
||||||
"client/MixinMCASpeechManager",
|
|
||||||
"client/MixinMCAPlayerExtendedModel",
|
|
||||||
"client/MixinPlayerModel",
|
"client/MixinPlayerModel",
|
||||||
"client/MixinCamera",
|
"client/MixinCamera",
|
||||||
"client/MixinLivingEntitySleeping"
|
"client/MixinLivingEntitySleeping"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 0
|
"defaultRequire": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user