Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
370
src/main/java/com/tiedup/remake/items/ItemGpsCollar.java
Normal file
370
src/main/java/com/tiedup/remake/items/ItemGpsCollar.java
Normal file
@@ -0,0 +1,370 @@
|
||||
package com.tiedup.remake.items;
|
||||
|
||||
import com.tiedup.remake.state.IRestrainable;
|
||||
import com.tiedup.remake.util.KidnappedHelper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
|
||||
* GPS Collar - Advanced shock collar with tracking and safe zone features.
|
||||
|
||||
*
|
||||
|
||||
* <p>Mechanics:</p>
|
||||
|
||||
* <ul>
|
||||
|
||||
* <li><b>Safe Zones:</b> Can store multiple coordinates (SafeSpots) where the wearer is allowed to be.</li>
|
||||
|
||||
* <li><b>Auto-Shock:</b> If the wearer is outside ALL active safe zones, they are shocked at intervals.</li>
|
||||
|
||||
* <li><b>Master Warning:</b> Masters receive an alert message when a safe zone violation is detected.</li>
|
||||
|
||||
* <li><b>Public Tracking:</b> If enabled, allows anyone with a Locator to see distance and direction.</li>
|
||||
|
||||
* </ul>
|
||||
|
||||
*/
|
||||
|
||||
public class ItemGpsCollar extends ItemShockCollar {
|
||||
|
||||
private static final String NBT_PUBLIC_TRACKING = "publicTracking";
|
||||
|
||||
private static final String NBT_GPS_ACTIVE = "gpsActive";
|
||||
|
||||
private static final String NBT_SAFE_SPOTS = "gpsSafeSpots";
|
||||
|
||||
private static final String NBT_SHOCK_INTERVAL = "gpsShockInterval";
|
||||
|
||||
private static final String NBT_WARN_MASTERS = "warn_masters";
|
||||
|
||||
private final int defaultInterval;
|
||||
|
||||
public ItemGpsCollar() {
|
||||
this(200); // 10 seconds default
|
||||
}
|
||||
|
||||
public ItemGpsCollar(int defaultInterval) {
|
||||
super();
|
||||
this.defaultInterval = defaultInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGPS() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Renders detailed GPS status, safe zone list, and alert settings in the item tooltip.
|
||||
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void appendHoverText(
|
||||
ItemStack stack,
|
||||
@Nullable Level level,
|
||||
List<Component> tooltip,
|
||||
TooltipFlag flag
|
||||
) {
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
|
||||
tooltip.add(
|
||||
Component.literal("GPS Enabled").withStyle(
|
||||
ChatFormatting.DARK_GREEN
|
||||
)
|
||||
);
|
||||
|
||||
if (hasPublicTracking(stack)) {
|
||||
tooltip.add(
|
||||
Component.literal("Public Tracking Enabled").withStyle(
|
||||
ChatFormatting.GREEN
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldWarnMasters(stack)) {
|
||||
tooltip.add(
|
||||
Component.literal("Alert Masters on Violation").withStyle(
|
||||
ChatFormatting.GOLD
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
List<SafeSpot> safeSpots = getSafeSpots(stack);
|
||||
|
||||
if (!safeSpots.isEmpty()) {
|
||||
tooltip.add(
|
||||
Component.literal("GPS Shocks: ")
|
||||
.withStyle(ChatFormatting.GREEN)
|
||||
.append(
|
||||
Component.literal(
|
||||
isActive(stack) ? "ENABLED" : "DISABLED"
|
||||
).withStyle(
|
||||
isActive(stack)
|
||||
? ChatFormatting.RED
|
||||
: ChatFormatting.GRAY
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
tooltip.add(
|
||||
Component.literal(
|
||||
"Safe Spots (" + safeSpots.size() + "):"
|
||||
).withStyle(ChatFormatting.GREEN)
|
||||
);
|
||||
|
||||
for (int i = 0; i < safeSpots.size(); i++) {
|
||||
SafeSpot spot = safeSpots.get(i);
|
||||
|
||||
tooltip.add(
|
||||
Component.literal(
|
||||
(spot.active ? "[+] " : "[-] ") +
|
||||
(i + 1) +
|
||||
": " +
|
||||
spot.x +
|
||||
"," +
|
||||
spot.y +
|
||||
"," +
|
||||
spot.z +
|
||||
" (Range: " +
|
||||
spot.distance +
|
||||
"m)"
|
||||
).withStyle(ChatFormatting.GRAY)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldWarnMasters(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
|
||||
// Default to true if tag doesn't exist
|
||||
|
||||
return (
|
||||
tag == null ||
|
||||
!tag.contains(NBT_WARN_MASTERS) ||
|
||||
tag.getBoolean(NBT_WARN_MASTERS)
|
||||
);
|
||||
}
|
||||
|
||||
public void setWarnMasters(ItemStack stack, boolean warn) {
|
||||
stack.getOrCreateTag().putBoolean(NBT_WARN_MASTERS, warn);
|
||||
}
|
||||
|
||||
public boolean hasPublicTracking(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
|
||||
return tag != null && tag.getBoolean(NBT_PUBLIC_TRACKING);
|
||||
}
|
||||
|
||||
public void setPublicTracking(ItemStack stack, boolean publicTracking) {
|
||||
stack.getOrCreateTag().putBoolean(NBT_PUBLIC_TRACKING, publicTracking);
|
||||
}
|
||||
|
||||
public boolean isActive(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
|
||||
// Default to active if tag doesn't exist
|
||||
|
||||
return (
|
||||
tag == null ||
|
||||
!tag.contains(NBT_GPS_ACTIVE) ||
|
||||
tag.getBoolean(NBT_GPS_ACTIVE)
|
||||
);
|
||||
}
|
||||
|
||||
public void setActive(ItemStack stack, boolean active) {
|
||||
stack.getOrCreateTag().putBoolean(NBT_GPS_ACTIVE, active);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Parses the NBT List into a Java List of SafeSpot objects.
|
||||
|
||||
*/
|
||||
|
||||
public List<SafeSpot> getSafeSpots(ItemStack stack) {
|
||||
List<SafeSpot> list = new ArrayList<>();
|
||||
|
||||
CompoundTag tag = stack.getTag();
|
||||
|
||||
if (tag != null && tag.contains(NBT_SAFE_SPOTS)) {
|
||||
ListTag spotList = tag.getList(NBT_SAFE_SPOTS, 10);
|
||||
|
||||
for (int i = 0; i < spotList.size(); i++) {
|
||||
list.add(new SafeSpot(spotList.getCompound(i)));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Adds a new safe zone to the collar's NBT data.
|
||||
|
||||
*/
|
||||
|
||||
public void addSafeSpot(
|
||||
ItemStack stack,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
String dimension,
|
||||
int distance
|
||||
) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
|
||||
ListTag spotList = tag.getList(NBT_SAFE_SPOTS, 10);
|
||||
|
||||
SafeSpot spot = new SafeSpot(x, y, z, dimension, distance, true);
|
||||
|
||||
spotList.add(spot.toNBT());
|
||||
|
||||
tag.put(NBT_SAFE_SPOTS, spotList);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Gets frequency of GPS violation shocks.
|
||||
|
||||
*/
|
||||
|
||||
public int getShockInterval(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
|
||||
if (tag != null && tag.contains(NBT_SHOCK_INTERVAL)) {
|
||||
return tag.getInt(NBT_SHOCK_INTERVAL);
|
||||
}
|
||||
|
||||
return defaultInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 14.1.4: Reset auto-shock timer when GPS collar is removed.
|
||||
*/
|
||||
@Override
|
||||
public void onUnequipped(ItemStack stack, LivingEntity entity) {
|
||||
// Use IRestrainable interface instead of Player-only
|
||||
IRestrainable state = KidnappedHelper.getKidnappedState(entity);
|
||||
if (state != null) {
|
||||
state.resetAutoShockTimer();
|
||||
}
|
||||
|
||||
super.onUnequipped(stack, entity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Represents a defined safe zone in the 3D world.
|
||||
|
||||
*/
|
||||
|
||||
public static class SafeSpot {
|
||||
|
||||
public int x, y, z;
|
||||
|
||||
public String dimension;
|
||||
|
||||
public int distance;
|
||||
|
||||
public boolean active;
|
||||
|
||||
public SafeSpot(
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
String dimension,
|
||||
int distance,
|
||||
boolean active
|
||||
) {
|
||||
this.x = x;
|
||||
|
||||
this.y = y;
|
||||
|
||||
this.z = z;
|
||||
|
||||
this.dimension = dimension;
|
||||
|
||||
this.distance = distance;
|
||||
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public SafeSpot(CompoundTag nbt) {
|
||||
this.x = nbt.getInt("x");
|
||||
|
||||
this.y = nbt.getInt("y");
|
||||
|
||||
this.z = nbt.getInt("z");
|
||||
|
||||
this.dimension = nbt.getString("dim");
|
||||
|
||||
this.distance = nbt.getInt("dist");
|
||||
|
||||
this.active = !nbt.contains("active") || nbt.getBoolean("active");
|
||||
}
|
||||
|
||||
public CompoundTag toNBT() {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
|
||||
nbt.putInt("x", x);
|
||||
|
||||
nbt.putInt("y", y);
|
||||
|
||||
nbt.putInt("z", z);
|
||||
|
||||
nbt.putString("dim", dimension);
|
||||
|
||||
nbt.putInt("dist", distance);
|
||||
|
||||
nbt.putBoolean("active", active);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Checks if an entity is within the cuboid boundaries of this safe zone.
|
||||
|
||||
* Faithful to original 1.12.2 distance logic.
|
||||
|
||||
*/
|
||||
|
||||
public boolean isInside(Entity entity) {
|
||||
if (!active) return true;
|
||||
|
||||
// LOW FIX: Cross-dimension GPS fix
|
||||
// If entity is in a different dimension, consider them as "inside" the zone
|
||||
// to prevent false positive shocks when traveling between dimensions
|
||||
if (
|
||||
!entity
|
||||
.level()
|
||||
.dimension()
|
||||
.location()
|
||||
.toString()
|
||||
.equals(dimension)
|
||||
) return true; // Changed from false to true
|
||||
|
||||
// Cuboid distance check
|
||||
|
||||
return (
|
||||
Math.abs(entity.getX() - x) < distance &&
|
||||
Math.abs(entity.getY() - y) < distance &&
|
||||
Math.abs(entity.getZ() - z) < distance
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user