Remove internal phase comments and format code

Strip all Phase references, TODO/FUTURE roadmap notes, and internal
planning comments from the codebase. Run Prettier for consistent
formatting across all Java files.
This commit is contained in:
NotEvil
2026-04-12 01:24:49 +02:00
parent 73d70e212d
commit a71093ba9c
482 changed files with 8500 additions and 5155 deletions

View File

@@ -32,11 +32,15 @@ import org.jetbrains.annotations.Nullable;
*/
public final class FurnitureParser {
private static final Logger LOGGER = LogManager.getLogger("TiedUpFurniture");
private static final Logger LOGGER = LogManager.getLogger(
"TiedUpFurniture"
);
private static final String TAG = "[FurnitureParser]";
/** Strict hex color pattern: # followed by exactly 6 hex digits. */
private static final Pattern HEX_COLOR = Pattern.compile("^#[0-9A-Fa-f]{6}$");
private static final Pattern HEX_COLOR = Pattern.compile(
"^#[0-9A-Fa-f]{6}$"
);
/** Maximum number of seats per furniture (bitmask limit: 8 bits). */
private static final int MAX_SEATS = 8;
@@ -51,7 +55,10 @@ public final class FurnitureParser {
* @return the parsed definition, or null if the file is invalid
*/
@Nullable
public static FurnitureDefinition parse(InputStream input, ResourceLocation fileId) {
public static FurnitureDefinition parse(
InputStream input,
ResourceLocation fileId
) {
try {
JsonObject root = JsonParser.parseReader(
new InputStreamReader(input, StandardCharsets.UTF_8)
@@ -59,7 +66,12 @@ public final class FurnitureParser {
return parseObject(root, fileId);
} catch (Exception e) {
LOGGER.error("{} Failed to parse JSON {}: {}", TAG, fileId, e.getMessage());
LOGGER.error(
"{} Failed to parse JSON {}: {}",
TAG,
fileId,
e.getMessage()
);
return null;
}
}
@@ -72,7 +84,10 @@ public final class FurnitureParser {
* @return the parsed definition, or null if validation fails
*/
@Nullable
public static FurnitureDefinition parseObject(JsonObject root, ResourceLocation fileId) {
public static FurnitureDefinition parseObject(
JsonObject root,
ResourceLocation fileId
) {
// --- Required: id ---
String idStr = getStringOrNull(root, "id");
if (idStr == null || idStr.isEmpty()) {
@@ -81,7 +96,12 @@ public final class FurnitureParser {
}
ResourceLocation id = ResourceLocation.tryParse(idStr);
if (id == null) {
LOGGER.error("{} Skipping {}: invalid id ResourceLocation '{}'", TAG, fileId, idStr);
LOGGER.error(
"{} Skipping {}: invalid id ResourceLocation '{}'",
TAG,
fileId,
idStr
);
return null;
}
@@ -103,7 +123,12 @@ public final class FurnitureParser {
}
ResourceLocation modelLocation = ResourceLocation.tryParse(modelStr);
if (modelLocation == null) {
LOGGER.error("{} Skipping {}: invalid model ResourceLocation '{}'", TAG, fileId, modelStr);
LOGGER.error(
"{} Skipping {}: invalid model ResourceLocation '{}'",
TAG,
fileId,
modelStr
);
return null;
}
@@ -115,15 +140,27 @@ public final class FurnitureParser {
}
// --- Optional: supports_color (default false) ---
boolean supportsColor = getBooleanOrDefault(root, "supports_color", false);
boolean supportsColor = getBooleanOrDefault(
root,
"supports_color",
false
);
// --- Optional: hitbox (defaults: 1.0 x 1.0, clamped [0.1, 5.0]) ---
float hitboxWidth = 1.0f;
float hitboxHeight = 1.0f;
if (root.has("hitbox") && root.get("hitbox").isJsonObject()) {
JsonObject hitbox = root.getAsJsonObject("hitbox");
hitboxWidth = clamp(getFloatOrDefault(hitbox, "width", 1.0f), 0.1f, 5.0f);
hitboxHeight = clamp(getFloatOrDefault(hitbox, "height", 1.0f), 0.1f, 5.0f);
hitboxWidth = clamp(
getFloatOrDefault(hitbox, "width", 1.0f),
0.1f,
5.0f
);
hitboxHeight = clamp(
getFloatOrDefault(hitbox, "height", 1.0f),
0.1f,
5.0f
);
}
// --- Optional: placement ---
@@ -139,14 +176,22 @@ public final class FurnitureParser {
boolean lockable = getBooleanOrDefault(root, "lockable", false);
// --- Optional: break_resistance (default 100, clamped [1, 10000]) ---
float breakResistance = clamp(getFloatOrDefault(root, "break_resistance", 100.0f), 1.0f, 10000.0f);
float breakResistance = clamp(
getFloatOrDefault(root, "break_resistance", 100.0f),
1.0f,
10000.0f
);
// --- Optional: drop_on_break (default true) ---
boolean dropOnBreak = getBooleanOrDefault(root, "drop_on_break", true);
// --- Required: seats (non-empty array, size [1, 8]) ---
if (!root.has("seats") || !root.get("seats").isJsonArray()) {
LOGGER.error("{} Skipping {}: missing or invalid 'seats' array", TAG, fileId);
LOGGER.error(
"{} Skipping {}: missing or invalid 'seats' array",
TAG,
fileId
);
return null;
}
JsonArray seatsArray = root.getAsJsonArray("seats");
@@ -155,18 +200,33 @@ public final class FurnitureParser {
return null;
}
if (seatsArray.size() > MAX_SEATS) {
LOGGER.error("{} Skipping {}: 'seats' array has {} entries (max {})",
TAG, fileId, seatsArray.size(), MAX_SEATS);
LOGGER.error(
"{} Skipping {}: 'seats' array has {} entries (max {})",
TAG,
fileId,
seatsArray.size(),
MAX_SEATS
);
return null;
}
List<SeatDefinition> seats = new ArrayList<>(seatsArray.size());
for (int i = 0; i < seatsArray.size(); i++) {
if (!seatsArray.get(i).isJsonObject()) {
LOGGER.error("{} Skipping {}: seats[{}] is not a JSON object", TAG, fileId, i);
LOGGER.error(
"{} Skipping {}: seats[{}] is not a JSON object",
TAG,
fileId,
i
);
return null;
}
SeatDefinition seat = parseSeat(seatsArray.get(i).getAsJsonObject(), i, lockable, fileId);
SeatDefinition seat = parseSeat(
seatsArray.get(i).getAsJsonObject(),
i,
lockable,
fileId
);
if (seat == null) {
// parseSeat already logged the error
return null;
@@ -184,15 +244,30 @@ public final class FurnitureParser {
String category = getStringOrDefault(root, "category", "furniture");
// --- Optional: icon (item model ResourceLocation for inventory sprite) ---
ResourceLocation icon = parseOptionalResourceLocation(root, "icon", fileId);
ResourceLocation icon = parseOptionalResourceLocation(
root,
"icon",
fileId
);
return new FurnitureDefinition(
id, displayName, translationKey, modelLocation,
tintChannels, supportsColor,
hitboxWidth, hitboxHeight,
snapToWall, floorOnly,
lockable, breakResistance, dropOnBreak,
seats, feedback, category, icon
id,
displayName,
translationKey,
modelLocation,
tintChannels,
supportsColor,
hitboxWidth,
hitboxHeight,
snapToWall,
floorOnly,
lockable,
breakResistance,
dropOnBreak,
seats,
feedback,
category,
icon
);
}
@@ -208,47 +283,85 @@ public final class FurnitureParser {
* @return the parsed seat, or null on validation failure
*/
@Nullable
private static SeatDefinition parseSeat(JsonObject obj, int index,
boolean parentLockable,
ResourceLocation fileId) {
private static SeatDefinition parseSeat(
JsonObject obj,
int index,
boolean parentLockable,
ResourceLocation fileId
) {
// Required: id (must not contain ':')
String seatId = getStringOrNull(obj, "id");
if (seatId == null || seatId.isEmpty()) {
LOGGER.error("{} Skipping {}: seats[{}] missing 'id'", TAG, fileId, index);
LOGGER.error(
"{} Skipping {}: seats[{}] missing 'id'",
TAG,
fileId,
index
);
return null;
}
if (seatId.contains(":")) {
LOGGER.error("{} Skipping {}: seats[{}] id '{}' must not contain ':'",
TAG, fileId, index, seatId);
LOGGER.error(
"{} Skipping {}: seats[{}] id '{}' must not contain ':'",
TAG,
fileId,
index,
seatId
);
return null;
}
// Required: armature
String armature = getStringOrNull(obj, "armature");
if (armature == null || armature.isEmpty()) {
LOGGER.error("{} Skipping {}: seats[{}] missing 'armature'", TAG, fileId, index);
LOGGER.error(
"{} Skipping {}: seats[{}] missing 'armature'",
TAG,
fileId,
index
);
return null;
}
// Optional: blocked_regions (unknown region = fatal for entire furniture)
Set<BodyRegionV2> blockedRegions = parseBlockedRegions(obj, index, fileId);
Set<BodyRegionV2> blockedRegions = parseBlockedRegions(
obj,
index,
fileId
);
if (blockedRegions == null) {
// parseBlockedRegions returns null ONLY on unknown region name (fatal)
return null;
}
// Optional: lockable (inherits from top-level)
boolean seatLockable = getBooleanOrDefault(obj, "lockable", parentLockable);
boolean seatLockable = getBooleanOrDefault(
obj,
"lockable",
parentLockable
);
// Optional: locked_difficulty (clamped [1, 10000], default 1)
int lockedDifficulty = clampInt(getIntOrDefault(obj, "locked_difficulty", 1), 1, 10000);
int lockedDifficulty = clampInt(
getIntOrDefault(obj, "locked_difficulty", 1),
1,
10000
);
// Optional: item_difficulty_bonus (default false)
boolean itemDifficultyBonus = getBooleanOrDefault(obj, "item_difficulty_bonus", false);
boolean itemDifficultyBonus = getBooleanOrDefault(
obj,
"item_difficulty_bonus",
false
);
return new SeatDefinition(
seatId, armature, blockedRegions,
seatLockable, lockedDifficulty, itemDifficultyBonus
seatId,
armature,
blockedRegions,
seatLockable,
lockedDifficulty,
itemDifficultyBonus
);
}
@@ -257,15 +370,25 @@ public final class FurnitureParser {
* Returns null (fatal) if any region name is unknown.
*/
@Nullable
private static Set<BodyRegionV2> parseBlockedRegions(JsonObject obj, int seatIndex,
ResourceLocation fileId) {
if (!obj.has("blocked_regions") || !obj.get("blocked_regions").isJsonArray()) {
return Collections.unmodifiableSet(EnumSet.noneOf(BodyRegionV2.class));
private static Set<BodyRegionV2> parseBlockedRegions(
JsonObject obj,
int seatIndex,
ResourceLocation fileId
) {
if (
!obj.has("blocked_regions") ||
!obj.get("blocked_regions").isJsonArray()
) {
return Collections.unmodifiableSet(
EnumSet.noneOf(BodyRegionV2.class)
);
}
JsonArray arr = obj.getAsJsonArray("blocked_regions");
if (arr.isEmpty()) {
return Collections.unmodifiableSet(EnumSet.noneOf(BodyRegionV2.class));
return Collections.unmodifiableSet(
EnumSet.noneOf(BodyRegionV2.class)
);
}
EnumSet<BodyRegionV2> regions = EnumSet.noneOf(BodyRegionV2.class);
@@ -274,15 +397,25 @@ public final class FurnitureParser {
try {
name = elem.getAsString().toUpperCase();
} catch (Exception e) {
LOGGER.error("{} Skipping {}: seats[{}] invalid element in 'blocked_regions': {}",
TAG, fileId, seatIndex, e.getMessage());
LOGGER.error(
"{} Skipping {}: seats[{}] invalid element in 'blocked_regions': {}",
TAG,
fileId,
seatIndex,
e.getMessage()
);
return null;
}
BodyRegionV2 region = BodyRegionV2.fromName(name);
if (region == null) {
LOGGER.error("{} Skipping {}: seats[{}] unknown body region '{}'",
TAG, fileId, seatIndex, name);
LOGGER.error(
"{} Skipping {}: seats[{}] unknown body region '{}'",
TAG,
fileId,
seatIndex,
name
);
return null;
}
regions.add(region);
@@ -293,7 +426,10 @@ public final class FurnitureParser {
// ===== Feedback Parsing =====
private static FurnitureFeedback parseFeedback(JsonObject obj, ResourceLocation fileId) {
private static FurnitureFeedback parseFeedback(
JsonObject obj,
ResourceLocation fileId
) {
return new FurnitureFeedback(
parseOptionalResourceLocation(obj, "mount_sound", fileId),
parseOptionalResourceLocation(obj, "lock_sound", fileId),
@@ -311,8 +447,14 @@ public final class FurnitureParser {
* Returns empty map if field is absent. Returns null if any value is invalid hex.
*/
@Nullable
private static Map<String, Integer> parseTintChannels(JsonObject root, ResourceLocation fileId) {
if (!root.has("tint_channels") || !root.get("tint_channels").isJsonObject()) {
private static Map<String, Integer> parseTintChannels(
JsonObject root,
ResourceLocation fileId
) {
if (
!root.has("tint_channels") ||
!root.get("tint_channels").isJsonObject()
) {
return Map.of();
}
@@ -324,15 +466,24 @@ public final class FurnitureParser {
try {
hex = entry.getValue().getAsString();
} catch (Exception e) {
LOGGER.error("{} Skipping {}: tint_channels '{}' value is not a string",
TAG, fileId, entry.getKey());
LOGGER.error(
"{} Skipping {}: tint_channels '{}' value is not a string",
TAG,
fileId,
entry.getKey()
);
return null;
}
if (!HEX_COLOR.matcher(hex).matches()) {
LOGGER.error("{} Skipping {}: tint_channels '{}' has invalid hex color '{}' "
+ "(expected '#' followed by 6 hex digits)",
TAG, fileId, entry.getKey(), hex);
LOGGER.error(
"{} Skipping {}: tint_channels '{}' has invalid hex color '{}' " +
"(expected '#' followed by 6 hex digits)",
TAG,
fileId,
entry.getKey(),
hex
);
return null;
}
@@ -355,12 +506,20 @@ public final class FurnitureParser {
}
}
private static String getStringOrDefault(JsonObject obj, String key, String defaultValue) {
private static String getStringOrDefault(
JsonObject obj,
String key,
String defaultValue
) {
String value = getStringOrNull(obj, key);
return (value != null && !value.isEmpty()) ? value : defaultValue;
}
private static int getIntOrDefault(JsonObject obj, String key, int defaultValue) {
private static int getIntOrDefault(
JsonObject obj,
String key,
int defaultValue
) {
if (!obj.has(key) || obj.get(key).isJsonNull()) return defaultValue;
try {
return obj.get(key).getAsInt();
@@ -369,7 +528,11 @@ public final class FurnitureParser {
}
}
private static float getFloatOrDefault(JsonObject obj, String key, float defaultValue) {
private static float getFloatOrDefault(
JsonObject obj,
String key,
float defaultValue
) {
if (!obj.has(key) || obj.get(key).isJsonNull()) return defaultValue;
try {
return obj.get(key).getAsFloat();
@@ -378,7 +541,11 @@ public final class FurnitureParser {
}
}
private static boolean getBooleanOrDefault(JsonObject obj, String key, boolean defaultValue) {
private static boolean getBooleanOrDefault(
JsonObject obj,
String key,
boolean defaultValue
) {
if (!obj.has(key) || obj.get(key).isJsonNull()) return defaultValue;
try {
return obj.get(key).getAsBoolean();
@@ -389,13 +556,21 @@ public final class FurnitureParser {
@Nullable
private static ResourceLocation parseOptionalResourceLocation(
JsonObject obj, String key, ResourceLocation fileId
JsonObject obj,
String key,
ResourceLocation fileId
) {
String value = getStringOrNull(obj, key);
if (value == null || value.isEmpty()) return null;
ResourceLocation loc = ResourceLocation.tryParse(value);
if (loc == null) {
LOGGER.warn("{} In {}: invalid ResourceLocation for '{}': '{}'", TAG, fileId, key, value);
LOGGER.warn(
"{} In {}: invalid ResourceLocation for '{}': '{}'",
TAG,
fileId,
key,
value
);
}
return loc;
}