Добавить испытания и прогрессию по LevelID
This commit is contained in:
@@ -24,6 +24,7 @@ public final class LevelCatalogLoader {
|
||||
|
||||
List<LevelDefinition> result = new ArrayList<>();
|
||||
Set<Integer> numbers = new HashSet<>();
|
||||
Set<String> levelIds = new HashSet<>();
|
||||
String directory = directory(index);
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
String path = directory + entries.get(i);
|
||||
@@ -37,6 +38,10 @@ public final class LevelCatalogLoader {
|
||||
throw new IllegalArgumentException(index + ".levels[" + i
|
||||
+ "] duplicates level number " + level.number);
|
||||
}
|
||||
if (!levelIds.add(level.levelId)) {
|
||||
throw new IllegalArgumentException(index + ".levels[" + i
|
||||
+ "] duplicates level id '" + level.levelId + "'");
|
||||
}
|
||||
int expected = i + 1;
|
||||
if (level.number != expected) {
|
||||
throw new IllegalArgumentException(index + ".levels[" + i + "] expected level number "
|
||||
|
||||
@@ -89,6 +89,9 @@ public final class LevelContentTool {
|
||||
}
|
||||
rect(value, "spawn", 0, new LevelDefinition.Box(level.spawnX, level.spawnY, 62f, 100f), "#22c55e");
|
||||
rect(value, "goal", 0, level.goal, "#38bdf8");
|
||||
if (level.collectible != null) {
|
||||
rect(value, "collectible", 0, level.collectible, "#facc15");
|
||||
}
|
||||
value.append("</svg>\n");
|
||||
return value.toString();
|
||||
}
|
||||
@@ -107,6 +110,10 @@ public final class LevelContentTool {
|
||||
row(value, level.number, "spawn", 0, "PLAYER", new LevelDefinition.Box(
|
||||
level.spawnX, level.spawnY, 62f, 100f), 0f, 0f, "");
|
||||
row(value, level.number, "goal", 0, "GOAL", level.goal, 0f, 0f, "");
|
||||
if (level.collectible != null) {
|
||||
row(value, level.number, "collectible", 0, "CACHE", level.collectible,
|
||||
0f, 0f, level.levelId);
|
||||
}
|
||||
for (int i = 0; i < level.platforms.size(); i++) {
|
||||
LevelDefinition.Platform item = level.platforms.get(i);
|
||||
row(value, level.number, "platform", i, item.isMoving() ? "MOVING" : "STATIC",
|
||||
|
||||
@@ -131,6 +131,8 @@ public final class LevelDefinition {
|
||||
public final int number;
|
||||
public final int formatVersion;
|
||||
public final int physicsVersion;
|
||||
public final String levelId;
|
||||
public final String worldId;
|
||||
public final String title;
|
||||
public final String hint;
|
||||
public final String titleRu;
|
||||
@@ -142,6 +144,7 @@ public final class LevelDefinition {
|
||||
public final Box goal;
|
||||
public final int targetDeaths;
|
||||
public final int targetSeconds;
|
||||
public final Box collectible;
|
||||
public final List<PhysicalObject> objects;
|
||||
public final List<Platform> platforms;
|
||||
public final List<Hazard> hazards;
|
||||
@@ -213,9 +216,41 @@ public final class LevelDefinition {
|
||||
List<Hazard> hazards,
|
||||
List<Switch> switches,
|
||||
List<Door> doors
|
||||
) {
|
||||
this(formatVersion, physicsVersion, defaultLevelId(number), "legacy",
|
||||
number, title, hint, titleRu, hintRu, worldWidth, worldHeight,
|
||||
spawnX, spawnY, goal, targetDeaths, targetSeconds, null, objects,
|
||||
platforms, hazards, switches, doors);
|
||||
}
|
||||
|
||||
public LevelDefinition(
|
||||
int formatVersion,
|
||||
int physicsVersion,
|
||||
String levelId,
|
||||
String worldId,
|
||||
int number,
|
||||
String title,
|
||||
String hint,
|
||||
String titleRu,
|
||||
String hintRu,
|
||||
float worldWidth,
|
||||
float worldHeight,
|
||||
float spawnX,
|
||||
float spawnY,
|
||||
Box goal,
|
||||
int targetDeaths,
|
||||
int targetSeconds,
|
||||
Box collectible,
|
||||
List<PhysicalObject> objects,
|
||||
List<Platform> platforms,
|
||||
List<Hazard> hazards,
|
||||
List<Switch> switches,
|
||||
List<Door> doors
|
||||
) {
|
||||
this.formatVersion = formatVersion;
|
||||
this.physicsVersion = physicsVersion;
|
||||
this.levelId = levelId;
|
||||
this.worldId = worldId;
|
||||
this.number = number;
|
||||
this.title = title;
|
||||
this.hint = hint;
|
||||
@@ -228,6 +263,7 @@ public final class LevelDefinition {
|
||||
this.goal = goal;
|
||||
this.targetDeaths = targetDeaths;
|
||||
this.targetSeconds = targetSeconds;
|
||||
this.collectible = collectible;
|
||||
this.objects = Collections.unmodifiableList(objects);
|
||||
this.platforms = Collections.unmodifiableList(platforms);
|
||||
this.hazards = Collections.unmodifiableList(hazards);
|
||||
@@ -235,6 +271,10 @@ public final class LevelDefinition {
|
||||
this.doors = Collections.unmodifiableList(doors);
|
||||
}
|
||||
|
||||
public static String defaultLevelId(int number) {
|
||||
return "legacy.level-" + (number < 10 ? "0" : "") + number;
|
||||
}
|
||||
|
||||
public boolean containsMechanic(HazardType type) {
|
||||
for (Hazard hazard : hazards) {
|
||||
if (hazard.type == type) return true;
|
||||
|
||||
@@ -41,11 +41,20 @@ public final class LevelJsonLoader {
|
||||
List<LevelDefinition.Hazard> hazards = hazards(root, source);
|
||||
List<LevelDefinition.Switch> switches = switches(root, source);
|
||||
List<LevelDefinition.Door> doors = doors(root, source);
|
||||
int number = integer(root, "number", source);
|
||||
String levelId = root.containsKey("id")
|
||||
? text(root, "id", source) : LevelDefinition.defaultLevelId(number);
|
||||
String worldId = root.containsKey("worldId")
|
||||
? text(root, "worldId", source) : "legacy";
|
||||
LevelDefinition.Box collectible = root.containsKey("collectible")
|
||||
? box(root.get("collectible"), source + ".collectible") : null;
|
||||
|
||||
return LevelValidator.validate(new LevelDefinition(
|
||||
integer(root, "formatVersion", source),
|
||||
integer(root, "physicsVersion", source),
|
||||
integer(root, "number", source),
|
||||
levelId,
|
||||
worldId,
|
||||
number,
|
||||
text(english, "title", source + ".copy.en"),
|
||||
text(english, "hint", source + ".copy.en"),
|
||||
text(russian, "title", source + ".copy.ru"),
|
||||
@@ -57,6 +66,7 @@ public final class LevelJsonLoader {
|
||||
box(required(root, "goal", source), source + ".goal"),
|
||||
integer(targets, "deaths", source + ".targets"),
|
||||
integer(targets, "seconds", source + ".targets"),
|
||||
collectible,
|
||||
objects,
|
||||
platforms,
|
||||
hazards,
|
||||
|
||||
@@ -109,6 +109,13 @@ public final class LevelValidator {
|
||||
for (int i = 0; i < level.doors.size(); i++) {
|
||||
box(level.doors.get(i).box, level, source + ".doors[" + i + "].box");
|
||||
}
|
||||
if (level.collectible != null) box(level.collectible, level, source + ".collectible");
|
||||
if (level.levelId == null || !level.levelId.matches("[a-z0-9][a-z0-9._-]{2,63}")) {
|
||||
throw invalid(source + ".id", "must be a stable lowercase identifier");
|
||||
}
|
||||
if (level.worldId == null || !level.worldId.matches("[a-z0-9][a-z0-9._-]{2,31}")) {
|
||||
throw invalid(source + ".worldId", "must be a stable lowercase identifier");
|
||||
}
|
||||
if (level.targetDeaths < 0) throw invalid(source + ".targets.deaths", "must not be negative");
|
||||
if (level.targetSeconds <= 0) throw invalid(source + ".targets.seconds", "must be positive");
|
||||
Set<String> signalSources = new HashSet<>();
|
||||
|
||||
Reference in New Issue
Block a user