mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 12:41:43 +00:00
dwa
This commit is contained in:
+15
-4
@@ -152,9 +152,19 @@ public final class ModdedDimensionManager {
|
||||
}
|
||||
|
||||
public static Handle createPersistent(MinecraftServer server, String dimensionId, String pack, String packDimensionKey, long seed) {
|
||||
Handle handle = create(server, dimensionId, pack, packDimensionKey, seed);
|
||||
ModdedDimensionRegistryStore.put(server, new ModdedDimensionRegistryStore.PersistentDimension(dimensionId, pack, packDimensionKey, seed));
|
||||
return handle;
|
||||
try {
|
||||
return create(server, dimensionId, pack, packDimensionKey, seed);
|
||||
} catch (Throwable e) {
|
||||
ModdedDimensionRegistryStore.remove(server, dimensionId);
|
||||
if (e instanceof RuntimeException runtimeException) {
|
||||
throw runtimeException;
|
||||
}
|
||||
if (e instanceof Error fatalError) {
|
||||
throw fatalError;
|
||||
}
|
||||
throw new IllegalStateException("Iris runtime dimension injection failed for " + dimensionId, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean removePersistent(MinecraftServer server, String dimensionId, boolean wipeStorage) {
|
||||
@@ -265,9 +275,10 @@ public final class ModdedDimensionManager {
|
||||
IrisDimension dimension = loadPackDimension(pack, packDimensionKey);
|
||||
String typeRef = ModdedForcedDatapack.dimensionTypeRef(dimension);
|
||||
ResourceKey<DimensionType> typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, Identifier.parse(typeRef));
|
||||
Holder.Reference<DimensionType> packType = ModdedForcedDatapack.requireRegisteredDimensionType(
|
||||
ModdedRuntimeRegistry.ensureCustomBiomes(registryAccess, dimension, pack);
|
||||
ModdedRuntimeRegistry.ensureDimensionType(registryAccess, registry, typeKey, typeRef, dimension);
|
||||
return ModdedForcedDatapack.requireRegisteredDimensionType(
|
||||
typeRef, registry.get(typeKey), pack, packDimensionKey);
|
||||
return packType;
|
||||
}
|
||||
|
||||
private static IrisDimension loadPackDimension(String pack, String packDimensionKey) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.iris.core.gui.GuiHost;
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.engine.decorator.DecoratorPlatformHooks;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineEffectsProvider;
|
||||
@@ -260,6 +261,7 @@ public final class ModdedEngineBootstrap {
|
||||
ModdedIrisLog.info("Iris " + moddedLoader.modVersion() + " bootstrapping on Minecraft " + moddedLoader.minecraftVersion() + " (" + loaderDescription + ")");
|
||||
selfTest(moddedLoader.getClass().getClassLoader());
|
||||
bind();
|
||||
IrisLanguage.initialize();
|
||||
MainWorldService.reconcileEarly();
|
||||
chunkGeneratorRegistration.run();
|
||||
ModdedIrisLog.info("Iris chunk generator registered as irisworldgen:iris");
|
||||
|
||||
+3
-1
@@ -19,6 +19,8 @@
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.iris.core.nms.datapack.DataVersion;
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
@@ -85,7 +87,7 @@ public final class ModdedForcedDatapack {
|
||||
private static Pack requireReadablePack(Path directory) {
|
||||
PackLocationInfo location = new PackLocationInfo(
|
||||
PACK_ID,
|
||||
Component.literal("Iris World Generation"),
|
||||
Component.literal(IrisLanguage.plain(RuntimeUiMessages.FORCED_DATAPACK_NAME)),
|
||||
PackSource.BUILT_IN,
|
||||
Optional.empty());
|
||||
PackSelectionConfig selection = new PackSelectionConfig(true, Pack.Position.TOP, true);
|
||||
|
||||
+10
-3
@@ -18,7 +18,10 @@
|
||||
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.PackDownloadMessages;
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,11 +41,11 @@ public final class ModdedPackInstaller {
|
||||
|
||||
public static boolean install(Path configDir, String pack, String branch, Consumer<String> feedback) {
|
||||
if (pack == null || !PACK_NAME.matcher(pack).matches()) {
|
||||
feedback.accept("Invalid pack name '" + pack + "' (allowed: a-z, 0-9, _ and -)");
|
||||
feedback.accept(IrisLanguage.plain(PackDownloadMessages.INVALID_PACK_NAME, MessageArgument.untrusted("pack", String.valueOf(pack))));
|
||||
return false;
|
||||
}
|
||||
if (branch == null || !BRANCH_NAME.matcher(branch).matches()) {
|
||||
feedback.accept("Invalid branch name '" + branch + "' (allowed: letters, digits, . _ and -)");
|
||||
feedback.accept(IrisLanguage.plain(PackDownloadMessages.INVALID_BRANCH_NAME, MessageArgument.untrusted("branch", String.valueOf(branch))));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -54,7 +57,11 @@ public final class ModdedPackInstaller {
|
||||
return PackDownloader.download(packs, "IrisDimensions/" + pack, branch, true, false, feedback) != null;
|
||||
} catch (IOException error) {
|
||||
LOGGER.error("Iris pack download failed for IrisDimensions/{} ({})", pack, branch, error);
|
||||
feedback.accept("Pack download failed: " + error.getClass().getSimpleName() + (error.getMessage() == null ? "" : " - " + error.getMessage()));
|
||||
feedback.accept(IrisLanguage.plain(
|
||||
PackDownloadMessages.DOWNLOAD_FAILED,
|
||||
MessageArgument.untrusted("type", error.getClass().getSimpleName()),
|
||||
MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(error))
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Servers
|
||||
* Copyright (c) 2026 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.nms.datapack.DataVersion;
|
||||
import art.arcane.iris.core.nms.datapack.IDataFixer;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisBiomeCustom;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.util.common.data.DataProvider;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.RegistrationInfo;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ModdedRuntimeRegistry {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
private ModdedRuntimeRegistry() {
|
||||
}
|
||||
|
||||
static void ensureDimensionType(RegistryAccess registryAccess, Registry<DimensionType> registry,
|
||||
ResourceKey<DimensionType> typeKey, String typeRef, IrisDimension dimension) {
|
||||
if (registry.get(typeKey).isPresent()) {
|
||||
return;
|
||||
}
|
||||
IDataFixer fixer = DataVersion.getLatest().get();
|
||||
String json = dimension.getDimensionType().toJson(fixer);
|
||||
DimensionType type = decode(registryAccess, DimensionType.DIRECT_CODEC, json, typeRef);
|
||||
registerIntoFrozen(registry, typeKey, type, typeRef);
|
||||
LOGGER.info("Iris registered runtime dimension type '{}'", typeRef);
|
||||
}
|
||||
|
||||
static void ensureCustomBiomes(RegistryAccess registryAccess, IrisDimension dimension, String pack) {
|
||||
File packFolder = ModdedWorldEngines.packFolder(pack);
|
||||
if (!packFolder.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
Registry<Biome> registry = registryAccess.lookupOrThrow(Registries.BIOME);
|
||||
IrisData data = IrisData.get(packFolder);
|
||||
DataProvider provider = () -> data;
|
||||
IDataFixer fixer = DataVersion.getLatest().get();
|
||||
String namespace = dimension.getLoadKey().toLowerCase(Locale.ROOT);
|
||||
Set<String> seen = new HashSet<>();
|
||||
int registered = 0;
|
||||
for (IrisBiome irisBiome : dimension.getAllBiomes(provider)) {
|
||||
if (!irisBiome.isCustom()) {
|
||||
continue;
|
||||
}
|
||||
for (IrisBiomeCustom customBiome : irisBiome.getCustomDerivitives()) {
|
||||
String biomeId = customBiome.getId();
|
||||
if (!seen.add(biomeId)) {
|
||||
continue;
|
||||
}
|
||||
String biomeRef = namespace + ":" + biomeId;
|
||||
ResourceKey<Biome> biomeKey = ResourceKey.create(Registries.BIOME, Identifier.parse(biomeRef));
|
||||
if (registry.get(biomeKey).isPresent()) {
|
||||
continue;
|
||||
}
|
||||
String json = customBiome.generateJson(fixer);
|
||||
Biome biome = decode(registryAccess, Biome.DIRECT_CODEC, json, biomeRef);
|
||||
registerIntoFrozen(registry, biomeKey, biome, biomeRef);
|
||||
registered++;
|
||||
}
|
||||
}
|
||||
if (registered > 0) {
|
||||
LOGGER.info("Iris registered {} runtime biome(s) for pack '{}'", registered, pack);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> T decode(RegistryAccess registryAccess, Codec<T> codec, String json, String ref) {
|
||||
JsonElement element = JsonParser.parseString(json);
|
||||
RegistryOps<JsonElement> ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess);
|
||||
return codec.parse(ops, element).getOrThrow((String message) ->
|
||||
new IllegalStateException("Iris could not decode runtime registry entry '" + ref + "': " + message));
|
||||
}
|
||||
|
||||
private static <T> Holder.Reference<T> registerIntoFrozen(Registry<T> registry, ResourceKey<T> key, T value, String ref) {
|
||||
if (!(registry instanceof MappedRegistry<T> mapped)) {
|
||||
throw new IllegalStateException("Iris cannot register '" + ref + "' at runtime: "
|
||||
+ registry.getClass().getName() + " is not a MappedRegistry");
|
||||
}
|
||||
synchronized (LOCK) {
|
||||
Optional<Holder.Reference<T>> raced = registry.get(key);
|
||||
if (raced.isPresent()) {
|
||||
return raced.get();
|
||||
}
|
||||
boolean wasFrozen = mapped.frozen;
|
||||
mapped.frozen = false;
|
||||
try {
|
||||
return mapped.register(key, value, RegistrationInfo.BUILT_IN);
|
||||
} finally {
|
||||
if (wasFrozen) {
|
||||
mapped.freeze();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+136
-120
@@ -19,6 +19,7 @@
|
||||
package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.localization.IrisMessages;
|
||||
import art.arcane.iris.core.gui.GuiHost;
|
||||
import art.arcane.iris.core.loader.IrisRegistrant;
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
@@ -106,6 +107,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class IrisModdedCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -386,27 +391,27 @@ public final class IrisModdedCommands {
|
||||
private static int editBiome(CommandSourceStack source, String key) {
|
||||
Engine engine = engineFor(source.getLevel());
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS));
|
||||
return 0;
|
||||
}
|
||||
IrisBiome biome;
|
||||
if (key == null || key.isBlank()) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "Console must name a biome: /iris edit biome <key>");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CONSOLE_MUST_NAME_BIOME_IRIS_EDIT_BIOME_KEY));
|
||||
return 0;
|
||||
}
|
||||
BlockPos pos = player.blockPosition();
|
||||
try {
|
||||
biome = engine.getBiome(pos.getX(), pos.getY() - engine.getMinHeight(), pos.getZ());
|
||||
} catch (Throwable e) {
|
||||
fail(source, "Biome lookup failed: " + e.getClass().getSimpleName());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_BIOME_LOOKUP_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
biome = engine.getData().getBiomeLoader().load(key.trim());
|
||||
if (biome == null) {
|
||||
fail(source, "Unknown biome: " + key);
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_UNKNOWN_BIOME, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -416,27 +421,27 @@ public final class IrisModdedCommands {
|
||||
private static int editRegion(CommandSourceStack source, String key) {
|
||||
Engine engine = engineFor(source.getLevel());
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_2));
|
||||
return 0;
|
||||
}
|
||||
IrisRegion region;
|
||||
if (key == null || key.isBlank()) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "Console must name a region: /iris edit region <key>");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CONSOLE_MUST_NAME_REGION_IRIS_EDIT_REGION_KEY));
|
||||
return 0;
|
||||
}
|
||||
BlockPos pos = player.blockPosition();
|
||||
try {
|
||||
region = engine.getRegion(pos.getX(), pos.getZ());
|
||||
} catch (Throwable e) {
|
||||
fail(source, "Region lookup failed: " + e.getClass().getSimpleName());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_REGION_LOOKUP_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
region = engine.getData().getRegionLoader().load(key.trim());
|
||||
if (region == null) {
|
||||
fail(source, "Unknown region: " + key);
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_UNKNOWN_REGION, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -446,7 +451,7 @@ public final class IrisModdedCommands {
|
||||
private static int editDimension(CommandSourceStack source) {
|
||||
Engine engine = engineFor(source.getLevel());
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_3));
|
||||
return 0;
|
||||
}
|
||||
return openJson(source, engine.getDimension());
|
||||
@@ -454,11 +459,11 @@ public final class IrisModdedCommands {
|
||||
|
||||
private static int openJson(CommandSourceStack source, IrisRegistrant registrant) {
|
||||
if (!GuiHost.isAvailable() || !Desktop.isDesktopSupported()) {
|
||||
fail(source, "Cannot open files here: " + ModdedGuiHost.guiUnavailableReason());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CANNOT_OPEN_FILES_HERE, MessageArgument.untrusted("value", ModdedGuiHost.guiUnavailableReason())));
|
||||
return 0;
|
||||
}
|
||||
if (registrant == null || registrant.getLoadFile() == null || !registrant.getLoadFile().isFile()) {
|
||||
fail(source, "Cannot find the file; perhaps it was not loaded directly from a file?");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CANNOT_FIND_FILE_PERHAPS_IT_WAS_NOT_LOADED_DIRECTLY_FROM));
|
||||
return 0;
|
||||
}
|
||||
File file = registrant.getLoadFile();
|
||||
@@ -466,29 +471,29 @@ public final class IrisModdedCommands {
|
||||
Desktop.getDesktop().open(file);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris edit failed to open {}", file, e);
|
||||
fail(source, "Could not open " + file.getName() + ": " + e.getClass().getSimpleName());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_COULD_NOT_OPEN, MessageArgument.untrusted("value", file.getName()), MessageArgument.untrusted("value2", e.getClass().getSimpleName())));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "Opening " + registrant.getTypeName() + " " + file.getName() + " in your editor.");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_OPENING_YOUR_EDITOR, MessageArgument.untrusted("value", registrant.getTypeName()), MessageArgument.untrusted("value2", file.getName())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int tp(CommandSourceStack source, ServerLevel level, ServerPlayer target) {
|
||||
ServerPlayer player = target != null ? target : source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "Console must name a player: /iris tp <dimension> <player>");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CONSOLE_MUST_NAME_PLAYER_IRIS_TP_DIMENSION_PLAYER));
|
||||
return 0;
|
||||
}
|
||||
if (!(level.getChunkSource().getGenerator() instanceof IrisModdedChunkGenerator)) {
|
||||
fail(source, level.dimension().identifier() + " is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_IS_NOT_GENERATED_BY_IRIS, MessageArgument.untrusted("value", level.dimension().identifier())));
|
||||
return 0;
|
||||
}
|
||||
String dimensionId = level.dimension().identifier().toString();
|
||||
if (!ModdedDimensionManager.teleport(player, source.getServer(), dimensionId, 8.5D, Double.MIN_VALUE, 8.5D)) {
|
||||
fail(source, "Teleport failed: dimension " + dimensionId + " is not loaded.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_TELEPORT_FAILED_DIMENSION_IS_NOT_LOADED, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "Teleporting " + player.getScoreboardName() + " to " + dimensionId + "...");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_TELEPORTING, MessageArgument.untrusted("value", player.getScoreboardName()), MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -496,16 +501,16 @@ public final class IrisModdedCommands {
|
||||
MinecraftServer server = source.getServer();
|
||||
ServerLevel level = target != null ? target : source.getLevel();
|
||||
if (!(level.getChunkSource().getGenerator() instanceof IrisModdedChunkGenerator)) {
|
||||
fail(source, level.dimension().identifier() + " is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_IS_NOT_GENERATED_BY_IRIS_2, MessageArgument.untrusted("value", level.dimension().identifier())));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel fallback = server.overworld();
|
||||
if (fallback == level) {
|
||||
fail(source, "Cannot evacuate the primary world; there is nowhere to send players.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CANNOT_EVACUATE_PRIMARY_WORLD_THERE_IS_NOWHERE_SEND_PLAYERS));
|
||||
return 0;
|
||||
}
|
||||
int count = ModdedDimensionManager.evacuate(server, level);
|
||||
ok(source, "Evacuated " + count + " player(s) from " + level.dimension().identifier() + " to " + fallback.dimension().identifier() + ".");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_EVACUATED_PLAYER_S_FROM, MessageArgument.untrusted("count", count), MessageArgument.untrusted("value", level.dimension().identifier()), MessageArgument.untrusted("value2", fallback.dimension().identifier())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -513,7 +518,7 @@ public final class IrisModdedCommands {
|
||||
boolean to = !IrisSettings.get().getGeneral().isDebug();
|
||||
IrisSettings.get().getGeneral().setDebug(to);
|
||||
IrisSettings.get().forceSave();
|
||||
ok(source, "Set debug to: " + to);
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SET_DEBUG, MessageArgument.untrusted("to", to)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -522,39 +527,51 @@ public final class IrisModdedCommands {
|
||||
IrisSettings.invalidate();
|
||||
}
|
||||
IrisSettings.get();
|
||||
ok(source, "Hotloaded settings");
|
||||
boolean localeLoaded = IrisLanguage.reload();
|
||||
if (localeLoaded) {
|
||||
ok(source, IrisLanguage.plain(
|
||||
IrisMessages.COMMAND_RELOAD_SUCCESS,
|
||||
MessageArgument.trusted("locale", IrisLanguage.activeLocale())
|
||||
));
|
||||
return 1;
|
||||
}
|
||||
fail(source, IrisLanguage.plain(
|
||||
IrisMessages.COMMAND_RELOAD_FAILED,
|
||||
MessageArgument.untrusted("locale", IrisSettings.get().getGeneral().getLanguage()),
|
||||
MessageArgument.trusted("activeLocale", IrisLanguage.activeLocale())
|
||||
));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int whatHand(CommandSourceStack source) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players (it inspects your held item).");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_IT_INSPECTS));
|
||||
return 0;
|
||||
}
|
||||
ItemStack stack = player.getMainHandItem();
|
||||
if (stack.isEmpty()) {
|
||||
fail(source, "Your main hand is empty.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_YOUR_MAIN_HAND_IS_EMPTY));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "Hand: " + BuiltInRegistries.ITEM.getKey(stack.getItem()) + " x" + stack.getCount());
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_HAND_X, MessageArgument.untrusted("value", BuiltInRegistries.ITEM.getKey(stack.getItem())), MessageArgument.untrusted("value2", stack.getCount())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int regen(CommandSourceStack source, int radius) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = source.getLevel();
|
||||
if (!(level.getChunkSource().getGenerator() instanceof IrisModdedChunkGenerator irisGenerator)) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_4));
|
||||
return 0;
|
||||
}
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_5));
|
||||
return 0;
|
||||
}
|
||||
ModdedRegen.start(source, level, irisGenerator, engine, player, radius);
|
||||
@@ -570,15 +587,15 @@ public final class IrisModdedCommands {
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
if (withDimension) {
|
||||
fail(source, level.dimension().identifier() + " is not generated by Iris; see /iris info for loaded Iris dimensions.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_IS_NOT_GENERATED_BY_IRIS_SEE_IRIS_INFO_LOADED_IRIS, MessageArgument.untrusted("value", level.dimension().identifier())));
|
||||
} else {
|
||||
fail(source, "The current dimension (" + level.dimension().identifier() + ") is not generated by Iris. Name one explicitly: /iris pregen start " + radius + " <dimension>; see /iris info for loaded Iris dimensions.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CURRENT_DIMENSION_IS_NOT_GENERATED_BY_IRIS_NAME_ONE_EXPLICITLY, MessageArgument.untrusted("value", level.dimension().identifier()), MessageArgument.untrusted("radius", radius)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
boolean showGui = gui && ModdedGuiHost.isGuiLaunchable();
|
||||
if (!ModdedPregenJob.start(source.getServer(), level, engine, radius, centerX, centerZ, showGui, sync, !nocache)) {
|
||||
fail(source, "A pregeneration task is already running. Stop it first with /iris pregen stop.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PREGENERATION_TASK_IS_ALREADY_RUNNING_STOP_IT_FIRST_WITH_IRIS));
|
||||
return 0;
|
||||
}
|
||||
ModdedPregenBossBar.begin(source.getPlayer());
|
||||
@@ -591,35 +608,34 @@ public final class IrisModdedCommands {
|
||||
guiNote = " (GUI requested but unavailable: " + ModdedGuiHost.guiUnavailableReason() + ")";
|
||||
}
|
||||
String modeNote = " Mode: " + (sync ? "sync" : "async") + (nocache ? ", cache disabled." : ", resumable (checkpoint cache).");
|
||||
ok(source, "Pregen started in " + level.dimension().identifier() + " of " + (radius * 2) + " by " + (radius * 2)
|
||||
+ " blocks from " + centerX + "," + centerZ + "." + modeNote + " Progress logs to console; see /iris pregen status." + guiNote);
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PREGEN_STARTED_BY_BLOCKS_FROM_PROGRESS_LOGS_CONSOLE_SEE_IRIS, MessageArgument.untrusted("value", level.dimension().identifier()), MessageArgument.untrusted("value2", (radius * 2)), MessageArgument.untrusted("value3", (radius * 2)), MessageArgument.untrusted("centerX", centerX), MessageArgument.untrusted("centerZ", centerZ), MessageArgument.untrusted("modeNote", modeNote), MessageArgument.untrusted("guiNote", guiNote)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int pregenStop(CommandSourceStack source) {
|
||||
if (ModdedPregenJob.stop()) {
|
||||
ModdedPregenBossBar.clear();
|
||||
ok(source, "Stopping pregeneration; finishing up the current region...");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_STOPPING_PREGENERATION_FINISHING_UP_CURRENT_REGION));
|
||||
return 1;
|
||||
}
|
||||
fail(source, "No active pregeneration task to stop.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_NO_ACTIVE_PREGENERATION_TASK_STOP));
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int pregenPause(CommandSourceStack source) {
|
||||
Boolean paused = ModdedPregenJob.pauseResume();
|
||||
if (paused == null) {
|
||||
fail(source, "No active pregeneration task to pause/resume.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_NO_ACTIVE_PREGENERATION_TASK_PAUSE_RESUME));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "Pregeneration is now " + (paused.booleanValue() ? "paused" : "running") + ".");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PREGENERATION_IS_NOW, MessageArgument.trusted("value", IrisLanguage.plain(paused.booleanValue() ? RuntimeUiMessages.STATUS_PAUSED_LOWER : RuntimeUiMessages.STATUS_RUNNING_LOWER))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int pregenStatus(CommandSourceStack source) {
|
||||
Component status = ModdedPregenJob.statusComponent();
|
||||
if (status == null) {
|
||||
fail(source, "No active pregeneration task.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_NO_ACTIVE_PREGENERATION_TASK));
|
||||
return 0;
|
||||
}
|
||||
ok(source, status);
|
||||
@@ -629,8 +645,7 @@ public final class IrisModdedCommands {
|
||||
private static int version(CommandSourceStack source) {
|
||||
ModdedLoader loader = ModdedEngineBootstrap.loader();
|
||||
int engines = engineCount(source.getServer());
|
||||
ok(source, "Iris " + loader.modVersion() + " by Volmit Software on " + loader.platformName()
|
||||
+ " (Minecraft " + loader.minecraftVersion() + "), " + engines + " Iris dimension(s)");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_IRIS_BY_VOLMIT_SOFTWARE_ON_MINECRAFT_IRIS_DIMENSION_S, MessageArgument.untrusted("value", loader.modVersion()), MessageArgument.untrusted("value2", loader.platformName()), MessageArgument.untrusted("value3", loader.minecraftVersion()), MessageArgument.untrusted("engines", engines)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -661,9 +676,13 @@ public final class IrisModdedCommands {
|
||||
+ " generated=" + engine.getGenerated()
|
||||
+ " data=" + engine.getData().getDataFolder().getAbsolutePath());
|
||||
}
|
||||
ok(source, "Loaded dimensions: " + total + " (" + iris + " Iris)");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_LOADED_DIMENSIONS_IRIS, MessageArgument.untrusted("total", total), MessageArgument.untrusted("iris", iris)));
|
||||
if (lines.isEmpty()) {
|
||||
ok(source, filter == null ? "No Iris dimensions are loaded." : "No Iris dimension matches '" + filter + "'.");
|
||||
if (filter == null) {
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_NO_IRIS_DIMENSIONS_ARE_LOADED));
|
||||
} else {
|
||||
ok(source, IrisLanguage.plain(RuntimeUiMessages.MODDED_NO_DIMENSION_MATCH, MessageArgument.untrusted("filter", filter)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
for (String line : lines) {
|
||||
@@ -675,58 +694,58 @@ public final class IrisModdedCommands {
|
||||
private static int what(CommandSourceStack source) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_2));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_6));
|
||||
return 0;
|
||||
}
|
||||
BlockPos pos = player.blockPosition();
|
||||
int relativeY = pos.getY() - engine.getMinHeight();
|
||||
try {
|
||||
IrisBiome biome = engine.getBiome(pos.getX(), relativeY, pos.getZ());
|
||||
ok(source, "Biome: " + biome.getLoadKey() + " (" + biome.getName() + ")");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_BIOME, MessageArgument.untrusted("value", biome.getLoadKey()), MessageArgument.untrusted("value2", biome.getName())));
|
||||
} catch (Throwable e) {
|
||||
fail(source, "Biome lookup failed: " + e.getClass().getSimpleName());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_BIOME_LOOKUP_FAILED_2, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
|
||||
}
|
||||
try {
|
||||
IrisRegion region = engine.getRegion(pos.getX(), pos.getZ());
|
||||
ok(source, "Region: " + region.getLoadKey() + " (" + region.getName() + ")");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_REGION, MessageArgument.untrusted("value", region.getLoadKey()), MessageArgument.untrusted("value2", region.getName())));
|
||||
} catch (Throwable e) {
|
||||
fail(source, "Region lookup failed: " + e.getClass().getSimpleName());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_REGION_LOOKUP_FAILED_2, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
|
||||
}
|
||||
try {
|
||||
IrisBiome cave = engine.getCaveBiome(pos.getX(), relativeY, pos.getZ());
|
||||
ok(source, "Cave biome: " + (cave == null ? "none" : cave.getLoadKey()));
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CAVE_BIOME, MessageArgument.untrusted("value", cave == null ? IrisLanguage.plain(RuntimeUiMessages.STATUS_NONE) : cave.getLoadKey())));
|
||||
} catch (Throwable e) {
|
||||
fail(source, "Cave biome lookup failed: " + e.getClass().getSimpleName());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_CAVE_BIOME_LOOKUP_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
|
||||
}
|
||||
int surfaceY = level.getHeight(Heightmap.Types.WORLD_SURFACE, pos.getX(), pos.getZ());
|
||||
BlockState surface = level.getBlockState(new BlockPos(pos.getX(), surfaceY - 1, pos.getZ()));
|
||||
ok(source, "Surface block: " + BuiltInRegistries.BLOCK.getKey(surface.getBlock()) + " (y=" + (surfaceY - 1) + ")");
|
||||
ok(source, "Position: " + pos.getX() + " " + pos.getY() + " " + pos.getZ() + " (chunk " + (pos.getX() >> 4) + "," + (pos.getZ() >> 4) + ")");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SURFACE_BLOCK_Y, MessageArgument.untrusted("value", BuiltInRegistries.BLOCK.getKey(surface.getBlock())), MessageArgument.untrusted("value2", (surfaceY - 1))));
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_POSITION_CHUNK, MessageArgument.untrusted("value", pos.getX()), MessageArgument.untrusted("value2", pos.getY()), MessageArgument.untrusted("value3", pos.getZ()), MessageArgument.untrusted("value4", (pos.getX() >> 4)), MessageArgument.untrusted("value5", (pos.getZ() >> 4))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int whatBlock(CommandSourceStack source) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players (it inspects the block you are looking at).");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_IT_INSPECTS_2));
|
||||
return 0;
|
||||
}
|
||||
HitResult hit = player.pick(128.0D, 1.0F, false);
|
||||
if (hit.getType() != HitResult.Type.BLOCK || !(hit instanceof BlockHitResult blockHit)) {
|
||||
fail(source, "Look at a block, not the sky.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_LOOK_AT_BLOCK_NOT_SKY));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = source.getLevel();
|
||||
BlockPos pos = blockHit.getBlockPos();
|
||||
BlockState state = level.getBlockState(pos);
|
||||
PlatformBlockState platform = ModdedBlockState.of(state, null);
|
||||
ok(source, "Block: " + platform.key() + " (y=" + pos.getY() + ")");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_BLOCK_Y, MessageArgument.untrusted("value", platform.key()), MessageArgument.untrusted("value2", pos.getY())));
|
||||
List<String> flags = new ArrayList<>();
|
||||
if (platform.isSolid()) {
|
||||
flags.add("solid");
|
||||
@@ -761,20 +780,27 @@ public final class IrisModdedCommands {
|
||||
if (platform.hasTileEntity()) {
|
||||
flags.add("tile entity");
|
||||
}
|
||||
ok(source, flags.isEmpty() ? "Properties: (none)" : "Properties: " + String.join(", ", flags));
|
||||
if (flags.isEmpty()) {
|
||||
ok(source, IrisLanguage.plain(IrisMessages.MODDED_PROPERTIES_NONE));
|
||||
return 1;
|
||||
}
|
||||
ok(source, IrisLanguage.plain(
|
||||
IrisMessages.MODDED_PROPERTIES,
|
||||
MessageArgument.untrusted("properties", String.join(", ", flags))
|
||||
));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int whatMarkers(CommandSourceStack source, String markerRaw) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players (markers render as particles around you).");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_MARKERS_RENDER));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_7));
|
||||
return 0;
|
||||
}
|
||||
String marker = markerRaw.trim();
|
||||
@@ -782,7 +808,7 @@ public final class IrisModdedCommands {
|
||||
int chunkX = origin.getX() >> 4;
|
||||
int chunkZ = origin.getZ() >> 4;
|
||||
MinecraftServer server = source.getServer();
|
||||
ok(source, "Scanning for '" + marker + "' markers around you...");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SCANNING_MARKERS_AROUND_YOU, MessageArgument.untrusted("marker", marker)));
|
||||
Thread thread = new Thread(() -> {
|
||||
List<int[]> hits = new ArrayList<>();
|
||||
MatterMarker matterMarker = new MatterMarker(marker);
|
||||
@@ -796,7 +822,7 @@ public final class IrisModdedCommands {
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris marker scan failed for {}", marker, e);
|
||||
server.execute(() -> fail(source, "Marker scan failed: " + e.getClass().getSimpleName()));
|
||||
server.execute(() -> fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_MARKER_SCAN_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()))));
|
||||
return;
|
||||
}
|
||||
server.execute(() -> {
|
||||
@@ -805,7 +831,7 @@ public final class IrisModdedCommands {
|
||||
hit[0] + 0.5D, hit[1] + 1.0D, hit[2] + 0.5D,
|
||||
3, 0.2D, 0.2D, 0.2D, 0.0D);
|
||||
}
|
||||
ok(source, "Found " + hits.size() + " nearby marker(s) (" + marker + ")");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_FOUND_NEARBY_MARKER_S, MessageArgument.untrusted("value", hits.size()), MessageArgument.untrusted("marker", marker)));
|
||||
});
|
||||
}, "Iris Marker Scan");
|
||||
thread.setDaemon(true);
|
||||
@@ -816,18 +842,18 @@ public final class IrisModdedCommands {
|
||||
private static int gotoBiome(CommandSourceStack source, String key) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_3));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_8));
|
||||
return 0;
|
||||
}
|
||||
IrisBiome biome = engine.getData().getBiomeLoader().load(key.trim());
|
||||
if (biome == null) {
|
||||
fail(source, "Unknown biome: " + key);
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_UNKNOWN_BIOME_2, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
locate(source, level, engine, player, Locator.surfaceBiome(biome.getLoadKey()), "biome " + biome.getLoadKey());
|
||||
@@ -837,22 +863,22 @@ public final class IrisModdedCommands {
|
||||
private static int gotoRegion(CommandSourceStack source, String key) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_4));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_9));
|
||||
return 0;
|
||||
}
|
||||
IrisRegion region = engine.getData().getRegionLoader().load(key.trim());
|
||||
if (region == null) {
|
||||
fail(source, "Unknown region: " + key);
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_UNKNOWN_REGION_2, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
if (!engine.getDimension().getRegions().contains(region.getLoadKey())) {
|
||||
fail(source, region.getLoadKey() + " is not defined in the dimension!");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_IS_NOT_DEFINED_DIMENSION, MessageArgument.untrusted("value", region.getLoadKey())));
|
||||
return 0;
|
||||
}
|
||||
locate(source, level, engine, player, Locator.region(region.getLoadKey()), "region " + region.getLoadKey());
|
||||
@@ -863,19 +889,17 @@ public final class IrisModdedCommands {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_10));
|
||||
return 0;
|
||||
}
|
||||
String key = keyRaw.trim();
|
||||
if (!engine.hasObjectPlacement(key)) {
|
||||
fail(source, key + " is not configured in any region/biome object placements ("
|
||||
+ engine.getData().getObjectLoader().getPossibleKeys().length + " object keys loaded).");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_IS_NOT_CONFIGURED_ANY_REGION_BIOME_OBJECT_PLACEMENTS_OBJECT_KEYS, MessageArgument.untrusted("key", key), MessageArgument.untrusted("value", engine.getData().getObjectLoader().getPossibleKeys().length)));
|
||||
return 0;
|
||||
}
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players. (object key '" + key + "' resolved against "
|
||||
+ engine.getData().getObjectLoader().getPossibleKeys().length + " loaded object keys)");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_OBJECT_KEY, MessageArgument.untrusted("key", key), MessageArgument.untrusted("value", engine.getData().getObjectLoader().getPossibleKeys().length)));
|
||||
return 0;
|
||||
}
|
||||
locate(source, level, engine, player, Locator.object(key), "object " + key);
|
||||
@@ -886,17 +910,17 @@ public final class IrisModdedCommands {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_11));
|
||||
return 0;
|
||||
}
|
||||
String key = keyRaw.trim();
|
||||
if (key.isEmpty()) {
|
||||
fail(source, "Name an Iris or native structure to locate.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_NAME_IRIS_NATIVE_STRUCTURE_LOCATE));
|
||||
return 0;
|
||||
}
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_5));
|
||||
return 0;
|
||||
}
|
||||
Optional<NativeStructureTarget> resolved = resolveNativeStructure(source, level, engine, key);
|
||||
@@ -905,7 +929,7 @@ public final class IrisModdedCommands {
|
||||
locateIrisStructure(source, level, engine, player, key);
|
||||
return 1;
|
||||
}
|
||||
fail(source, "Unknown structure '" + key + "'. Use tab completion to choose an Iris placement or a registered native/datapack structure.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_UNKNOWN_STRUCTURE_USE_TAB_COMPLETION_CHOOSE_IRIS_PLACEMENT_REGISTERED_NATIVE, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
NativeStructureTarget target = resolved.get();
|
||||
@@ -924,7 +948,7 @@ public final class IrisModdedCommands {
|
||||
fail(source, nativeUnavailableMessage(target.key(), target.availability()));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "Searching for native structure " + target.key() + " within " + NATIVE_STRUCTURE_LOCATE_RADIUS + " chunks...");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCHING_NATIVE_STRUCTURE_WITHIN_CHUNKS, MessageArgument.untrusted("value", target.key()), MessageArgument.untrusted("NATIVESTRUCTURELOCATERADIUS", NATIVE_STRUCTURE_LOCATE_RADIUS)));
|
||||
runNativeStructureLocate(source, level, player, target);
|
||||
return 1;
|
||||
}
|
||||
@@ -934,18 +958,17 @@ public final class IrisModdedCommands {
|
||||
MinecraftServer server = source.getServer();
|
||||
int blockX = player.blockPosition().getX();
|
||||
int blockZ = player.blockPosition().getZ();
|
||||
ok(source, "Searching for Iris-placed structure " + key + "...");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCHING_IRIS_PLACED_STRUCTURE, MessageArgument.untrusted("key", key)));
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
IrisStructureLocator.LocateResult result =
|
||||
IrisStructureLocator.locate(engine, key, blockX, blockZ, 1024);
|
||||
if (result.status() == IrisStructureLocator.LocateStatus.SEARCH_LIMIT_REACHED) {
|
||||
server.execute(() -> fail(source, "Unable to locate Iris-placed structure " + key
|
||||
+ ": the density search safety limit was reached before the full 1024-chunk radius was searched."));
|
||||
server.execute(() -> fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_UNABLE_LOCATE_IRIS_PLACED_STRUCTURE_DENSITY_SEARCH_SAFETY_LIMIT_WAS, MessageArgument.untrusted("key", key))));
|
||||
return;
|
||||
}
|
||||
if (!result.found()) {
|
||||
server.execute(() -> fail(source, "Could not find Iris-placed structure " + key + " within 1024 chunks."));
|
||||
server.execute(() -> fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_COULD_NOT_FIND_IRIS_PLACED_STRUCTURE_WITHIN_1024_CHUNKS, MessageArgument.untrusted("key", key))));
|
||||
return;
|
||||
}
|
||||
int targetX = result.originX();
|
||||
@@ -955,7 +978,7 @@ public final class IrisModdedCommands {
|
||||
"Iris-placed structure " + key));
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris structure locate failed for {}", key, e);
|
||||
server.execute(() -> fail(source, "Search failed: " + e.getClass().getSimpleName()));
|
||||
server.execute(() -> fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCH_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()))));
|
||||
}
|
||||
}, "Iris Structure Locator");
|
||||
thread.setDaemon(true);
|
||||
@@ -984,8 +1007,7 @@ public final class IrisModdedCommands {
|
||||
NATIVE_STRUCTURE_LOCATE_RADIUS,
|
||||
false);
|
||||
if (found == null) {
|
||||
fail(source, "Could not find native structure " + target.key() + " within "
|
||||
+ NATIVE_STRUCTURE_LOCATE_RADIUS + " chunks.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_COULD_NOT_FIND_NATIVE_STRUCTURE_WITHIN_CHUNKS, MessageArgument.untrusted("value", target.key()), MessageArgument.untrusted("NATIVESTRUCTURELOCATERADIUS", NATIVE_STRUCTURE_LOCATE_RADIUS)));
|
||||
return;
|
||||
}
|
||||
BlockPos position = found.getFirst();
|
||||
@@ -998,18 +1020,18 @@ public final class IrisModdedCommands {
|
||||
"native structure " + target.key());
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Native structure locate failed for {}", target.key(), e);
|
||||
fail(source, "Search for native structure " + target.key() + " failed: " + e.getClass().getSimpleName());
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCH_NATIVE_STRUCTURE_FAILED, MessageArgument.untrusted("value", target.key()), MessageArgument.untrusted("value2", e.getClass().getSimpleName())));
|
||||
}
|
||||
}
|
||||
|
||||
private static void teleportToStructure(CommandSourceStack source, ServerLevel level, ServerPlayer player,
|
||||
int targetX, int targetY, int targetZ, String label) {
|
||||
if (player.hasDisconnected() || player.isRemoved()) {
|
||||
fail(source, "The player disconnected before the structure search completed.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PLAYER_DISCONNECTED_BEFORE_STRUCTURE_SEARCH_COMPLETED));
|
||||
return;
|
||||
}
|
||||
if (player.level() != level) {
|
||||
fail(source, "You changed dimensions before the structure search completed; run the command again.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_YOU_CHANGED_DIMENSIONS_BEFORE_STRUCTURE_SEARCH_COMPLETED_RUN_COMMAND_AGAIN));
|
||||
return;
|
||||
}
|
||||
level.getChunk(targetX >> 4, targetZ >> 4);
|
||||
@@ -1017,17 +1039,17 @@ public final class IrisModdedCommands {
|
||||
boolean teleported = player.teleportTo(level, targetX + 0.5D, clampedY, targetZ + 0.5D,
|
||||
Set.<Relative>of(), player.getYRot(), player.getXRot(), false);
|
||||
if (!teleported) {
|
||||
fail(source, "Found " + label + " at " + targetX + " " + clampedY + " " + targetZ + ", but teleportation failed.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_FOUND_AT_BUT_TELEPORTATION_FAILED, MessageArgument.untrusted("label", label), MessageArgument.untrusted("targetX", targetX), MessageArgument.untrusted("clampedY", clampedY), MessageArgument.untrusted("targetZ", targetZ)));
|
||||
return;
|
||||
}
|
||||
ok(source, "Teleported to " + label + " at " + targetX + " " + clampedY + " " + targetZ);
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_TELEPORTED_AT, MessageArgument.untrusted("label", label), MessageArgument.untrusted("targetX", targetX), MessageArgument.untrusted("clampedY", clampedY), MessageArgument.untrusted("targetZ", targetZ)));
|
||||
}
|
||||
|
||||
static int verifyStructures(CommandSourceStack source, String keyRaw) {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_12));
|
||||
return 0;
|
||||
}
|
||||
String key = keyRaw == null ? "" : keyRaw.trim();
|
||||
@@ -1056,11 +1078,7 @@ public final class IrisModdedCommands {
|
||||
}
|
||||
}
|
||||
int irisPlaced = IrisStructureLocator.placedKeys(engine).size();
|
||||
ok(source, "Structure reachability: " + available + " native generation-eligible, " + irisPlaced
|
||||
+ " Iris-placed, " + disabled + " native disabled, " + suppressed
|
||||
+ " native replaced by Iris placements, " + unreachableBiomes
|
||||
+ " native excluded by this pack's biomes, and " + unsupported
|
||||
+ " registered native structures unsupported in this dimension. Use /iris structure verify <key> for one structure.");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_STRUCTURE_REACHABILITY_NATIVE_GENERATION_ELIGIBLE_IRIS_PLACED_NATIVE_DISABLED_NATIVE, MessageArgument.untrusted("available", available), MessageArgument.untrusted("irisPlaced", irisPlaced), MessageArgument.untrusted("disabled", disabled), MessageArgument.untrusted("suppressed", suppressed), MessageArgument.untrusted("unreachableBiomes", unreachableBiomes), MessageArgument.untrusted("unsupported", unsupported)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1068,24 +1086,22 @@ public final class IrisModdedCommands {
|
||||
Optional<NativeStructureTarget> target = resolveNativeStructure(source, level, engine, key);
|
||||
if (target.isEmpty()) {
|
||||
if (IrisStructureLocator.isPlaced(engine, key)) {
|
||||
ok(source, "Structure " + key + " is Iris-placed and locatable with /iris goto structure " + key + ".");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_STRUCTURE_IS_IRIS_PLACED_LOCATABLE_WITH_IRIS_GOTO_STRUCTURE, MessageArgument.untrusted("key", key), MessageArgument.untrusted("key2", key)));
|
||||
return 1;
|
||||
}
|
||||
fail(source, "Unknown structure '" + key + "'. It is neither Iris-placed nor registered by vanilla or a datapack.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_UNKNOWN_STRUCTURE_IT_IS_NEITHER_IRIS_PLACED_NOR_REGISTERED_BY, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
NativeStructureTarget resolved = target.get();
|
||||
if (resolved.availability() == NativeStructureAvailability.IRIS_SUPPRESSED) {
|
||||
ok(source, "Structure " + resolved.key()
|
||||
+ " is explicitly replaced by an Iris placement and locatable with /iris goto structure "
|
||||
+ resolved.key() + ".");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_STRUCTURE_IS_EXPLICITLY_REPLACED_BY_IRIS_PLACEMENT_LOCATABLE_WITH_IRIS, MessageArgument.untrusted("value", resolved.key()), MessageArgument.untrusted("value2", resolved.key())));
|
||||
return 1;
|
||||
}
|
||||
if (resolved.availability() != NativeStructureAvailability.AVAILABLE) {
|
||||
fail(source, nativeUnavailableMessage(resolved.key(), resolved.availability()));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "Native structure " + resolved.key() + " is enabled, supported by this dimension's generator state, and locatable with /iris goto structure " + resolved.key() + ".");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_NATIVE_STRUCTURE_IS_ENABLED_SUPPORTED_BY_THIS_DIMENSION_S_GENERATOR, MessageArgument.untrusted("value", resolved.key()), MessageArgument.untrusted("value2", resolved.key())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1162,13 +1178,13 @@ public final class IrisModdedCommands {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_13));
|
||||
return 0;
|
||||
}
|
||||
String type = typeRaw.trim();
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
fail(source, "This command can only be used by players. (POI type '" + type + "' accepted)");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_POI_TYPE, MessageArgument.untrusted("type", type)));
|
||||
return 0;
|
||||
}
|
||||
locate(source, level, engine, player, Locator.poi(type), "POI " + type);
|
||||
@@ -1179,13 +1195,13 @@ public final class IrisModdedCommands {
|
||||
MinecraftServer server = source.getServer();
|
||||
int chunkX = player.blockPosition().getX() >> 4;
|
||||
int chunkZ = player.blockPosition().getZ() >> 4;
|
||||
ok(source, "Searching for " + label + "...");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCHING, MessageArgument.untrusted("label", label)));
|
||||
CompletableFuture<Position2> search;
|
||||
try {
|
||||
search = locator.find(engine, new Position2(chunkX, chunkZ), LOCATE_TIMEOUT_MS, (Integer checks) -> {
|
||||
});
|
||||
} catch (WrongEngineBroException e) {
|
||||
fail(source, "The engine for this world has been closed; rejoin the dimension and try again.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_ENGINE_THIS_WORLD_HAS_BEEN_CLOSED_REJOIN_DIMENSION_TRY_AGAIN));
|
||||
return;
|
||||
}
|
||||
UUID playerId = player.getUUID();
|
||||
@@ -1212,7 +1228,7 @@ public final class IrisModdedCommands {
|
||||
LOGGER.error("Iris locate failed for {}", label, failure);
|
||||
server.execute(() -> {
|
||||
if (ACTIVE_LOCATE_REQUESTS.remove(playerId, search)) {
|
||||
fail(source, "Search failed: " + failure);
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_SEARCH_FAILED_2, MessageArgument.untrusted("failure", failure)));
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -1220,7 +1236,7 @@ public final class IrisModdedCommands {
|
||||
if (at == null) {
|
||||
server.execute(() -> {
|
||||
if (ACTIVE_LOCATE_REQUESTS.remove(playerId, search)) {
|
||||
fail(source, "Could not find " + label + " within the search timeout.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_COULD_NOT_FIND_WITHIN_SEARCH_TIMEOUT, MessageArgument.untrusted("label", label)));
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -1240,9 +1256,9 @@ public final class IrisModdedCommands {
|
||||
IrisContext.Scope ignored = IrisContext.open(engine, lease.sessionId(), null)) {
|
||||
int blockY = engine.getMinHeight() + engine.getHeight(blockX, blockZ, false) + 2;
|
||||
player.teleportTo(level, blockX + 0.5D, blockY, blockZ + 0.5D, Set.<Relative>of(), player.getYRot(), player.getXRot(), false);
|
||||
ok(source, "Teleported to " + label + " at " + blockX + " " + blockY + " " + blockZ);
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_TELEPORTED_AT_2, MessageArgument.untrusted("label", label), MessageArgument.untrusted("blockX", blockX), MessageArgument.untrusted("blockY", blockY), MessageArgument.untrusted("blockZ", blockZ)));
|
||||
} catch (GenerationSessionException e) {
|
||||
fail(source, "The engine changed while locating " + label + "; try again.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_ENGINE_CHANGED_WHILE_LOCATING_TRY_AGAIN, MessageArgument.untrusted("label", label)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1259,11 +1275,11 @@ public final class IrisModdedCommands {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_14));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "World seed: " + level.getSeed());
|
||||
ok(source, "Engine seed: " + engine.getSeedManager().getSeed() + " (mixed: " + engine.getSeedManager().getFullMixedSeed() + ")");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_WORLD_SEED, MessageArgument.untrusted("value", level.getSeed())));
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_ENGINE_SEED_MIXED, MessageArgument.untrusted("value", engine.getSeedManager().getSeed()), MessageArgument.untrusted("value2", engine.getSeedManager().getFullMixedSeed())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1271,7 +1287,7 @@ public final class IrisModdedCommands {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_15));
|
||||
return 0;
|
||||
}
|
||||
ModdedGoldenHash.start(source, level, engine, radius, threads, mode);
|
||||
@@ -1282,14 +1298,14 @@ public final class IrisModdedCommands {
|
||||
MinecraftServer server = source.getServer();
|
||||
boolean defaultOverworld = PackDownloader.isDefaultOverworld(pack);
|
||||
String downloadSource = defaultOverworld ? "beta release" : "branch " + branch;
|
||||
ok(source, "Downloading IrisDimensions/" + pack + " (" + downloadSource + ")...");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("downloadSource", downloadSource)));
|
||||
Thread thread = new Thread(() -> {
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), pack, branch,
|
||||
(String message) -> server.execute(() -> ok(source, message)));
|
||||
if (installed) {
|
||||
server.execute(() -> ok(source, "Pack '" + pack + "' installed. Its exact dimension types and custom biomes join the forced Iris datapack on the next server restart; restart before creating worlds from this pack."));
|
||||
server.execute(() -> ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_INSTALLED_ITS_EXACT_DIMENSION_TYPES_CUSTOM_BIOMES_JOIN_FORCED, MessageArgument.untrusted("pack", pack))));
|
||||
} else {
|
||||
server.execute(() -> fail(source, "Pack download failed for " + pack + " (" + downloadSource + "; see console)."));
|
||||
server.execute(() -> fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_DOWNLOAD_FAILED_SEE_CONSOLE, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("downloadSource", downloadSource))));
|
||||
}
|
||||
}, "Iris Pack Download");
|
||||
thread.setDaemon(true);
|
||||
@@ -1301,17 +1317,17 @@ public final class IrisModdedCommands {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
if (engine == null) {
|
||||
fail(source, "This dimension is not generated by Iris.");
|
||||
fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_16));
|
||||
return 0;
|
||||
}
|
||||
ok(source, "Generated: " + engine.getGenerated() + " chunk(s), " + String.format("%.1f", engine.getGeneratedPerSecond()) + "/s");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_GENERATED_CHUNK_S_S, MessageArgument.untrusted("value", engine.getGenerated()), MessageArgument.untrusted("value2", String.format("%.1f", engine.getGeneratedPerSecond()))));
|
||||
KMap<String, Double> pulled = engine.getMetrics().pull();
|
||||
Map<String, Double> sorted = new TreeMap<>(pulled);
|
||||
for (Map.Entry<String, Double> entry : sorted.entrySet()) {
|
||||
if (entry.getValue() == null || entry.getValue() <= 0D) {
|
||||
continue;
|
||||
}
|
||||
ok(source, " " + entry.getKey() + ": " + String.format("%.2f", entry.getValue()) + "ms");
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_MS, MessageArgument.untrusted("value", entry.getKey()), MessageArgument.untrusted("value2", String.format("%.2f", entry.getValue()))));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+120
-109
@@ -24,6 +24,12 @@ import net.minecraft.network.chat.ClickEvent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.HoverEvent;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import art.arcane.iris.core.localization.IrisMessages;
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedHelpMessages;
|
||||
import art.arcane.volmlib.util.director.help.DirectorHelpMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import art.arcane.volmlib.util.localization.TextKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -50,124 +56,124 @@ final class ModdedCommandHelp {
|
||||
|
||||
static {
|
||||
SECTIONS.put("", List.of(
|
||||
Entry.command("version", "", "Print version information"),
|
||||
Entry.command("info", "[dimension]", "List loaded Iris dimensions and pack details"),
|
||||
Entry.command("what", "[block|hand|markers]", "Inspect the Iris biome, region, cave biome, surface and chunk at your position, the block you look at, your held item, or nearby markers"),
|
||||
Entry.group("find", "Find and teleport to Iris biomes, regions, objects, Iris structures, native structures and points of interest", "goto"),
|
||||
Entry.command("tp", "<dimension> [player]", "Teleport yourself or a named player into a loaded Iris dimension"),
|
||||
Entry.command("evacuate", "[dimension]", "Teleport every player out of an Iris dimension to the primary world spawn"),
|
||||
Entry.command("seed", "", "Print world and engine seed information"),
|
||||
Entry.command("debug", "", "Toggle Iris debug logging and save settings.json"),
|
||||
Entry.command("reload", "", "Reload settings.json (also hotloaded automatically every 3s)"),
|
||||
Entry.command("download", "<pack> [branch]", "Download a pack project", "dl"),
|
||||
Entry.command("metrics", "", "Print generation metrics for your current Iris dimension", "measure"),
|
||||
Entry.command("regen", "[radius]", "Delete and regenerate nearby chunks in place", "rg"),
|
||||
Entry.group("pregen", "Pregenerate an Iris dimension", "pregenerate"),
|
||||
Entry.command("wand", "", "Get an Iris object wand"),
|
||||
Entry.group("object", "Object wand, save, paste, analyze and undo tools", "o"),
|
||||
Entry.group("edit", "Open pack biome, region and dimension json files in your desktop editor"),
|
||||
Entry.command("create", "<name> <pack|pack:dimensionKey> [seed]", "Create and inject a persistent Iris dimension; quote pack:dimensionKey to pick a specific pack dimension"),
|
||||
Entry.group("studio", "Pack project creation, packaging and reports", "std", "s"),
|
||||
Entry.group("pack", "Pack validation and maintenance", "pk"),
|
||||
Entry.group("world", "Runtime Iris dimension creation, removal and status", "w"),
|
||||
Entry.group("datapack", "World datapack install and status helpers", "datapacks", "dp"),
|
||||
Entry.group("structure", "Iris structure index, info and placement tools", "struct", "str"),
|
||||
Entry.command("goldenhash", "[radius] [threads] [capture|verify]", "Generate deterministic block hashes for parity testing", "gold"),
|
||||
Entry.group("developer", "Developer diagnostics: Sentry test, network interfaces, region-file scan", "dev")
|
||||
Entry.command("version", "", ModdedHelpMessages.COMMAND_VERSION_PRINT_VERSION_INFORMATION),
|
||||
Entry.command("info", "[dimension]", ModdedHelpMessages.COMMAND_INFO_LIST_LOADED_IRIS_DIMENSIONS_AND_PACK_DETAILS),
|
||||
Entry.command("what", "[block|hand|markers]", ModdedHelpMessages.COMMAND_WHAT_INSPECT_THE_IRIS_BIOME_REGION_CAVE_BIOME_SURFACE_AND_CHUNK_AT_YOUR),
|
||||
Entry.group("find", ModdedHelpMessages.GROUP_FIND_FIND_AND_TELEPORT_TO_IRIS_BIOMES_REGIONS_OBJECTS_IRIS_STRUCTURES_NATIVE_STRUCTURES, "goto"),
|
||||
Entry.command("tp", "<dimension> [player]", ModdedHelpMessages.COMMAND_TP_TELEPORT_YOURSELF_OR_A_NAMED_PLAYER_INTO_A_LOADED_IRIS_DIMENSION),
|
||||
Entry.command("evacuate", "[dimension]", ModdedHelpMessages.COMMAND_EVACUATE_TELEPORT_EVERY_PLAYER_OUT_OF_AN_IRIS_DIMENSION_TO_THE_PRIMARY_WORLD),
|
||||
Entry.command("seed", "", ModdedHelpMessages.COMMAND_SEED_PRINT_WORLD_AND_ENGINE_SEED_INFORMATION),
|
||||
Entry.command("debug", "", ModdedHelpMessages.COMMAND_DEBUG_TOGGLE_IRIS_DEBUG_LOGGING_AND_SAVE_SETTINGS_JSON),
|
||||
Entry.command("reload", "", ModdedHelpMessages.COMMAND_RELOAD_RELOAD_SETTINGS_JSON_ALSO_HOTLOADED_AUTOMATICALLY_EVERY_3S),
|
||||
Entry.command("download", "<pack> [branch]", ModdedHelpMessages.COMMAND_DOWNLOAD_DOWNLOAD_A_PACK_PROJECT, "dl"),
|
||||
Entry.command("metrics", "", ModdedHelpMessages.COMMAND_METRICS_PRINT_GENERATION_METRICS_FOR_YOUR_CURRENT_IRIS_DIMENSION, "measure"),
|
||||
Entry.command("regen", "[radius]", ModdedHelpMessages.COMMAND_REGEN_DELETE_AND_REGENERATE_NEARBY_CHUNKS_IN_PLACE, "rg"),
|
||||
Entry.group("pregen", ModdedHelpMessages.GROUP_PREGEN_PREGENERATE_AN_IRIS_DIMENSION, "pregenerate"),
|
||||
Entry.command("wand", "", ModdedHelpMessages.COMMAND_WAND_GET_AN_IRIS_OBJECT_WAND),
|
||||
Entry.group("object", ModdedHelpMessages.GROUP_OBJECT_OBJECT_WAND_SAVE_PASTE_ANALYZE_AND_UNDO_TOOLS, "o"),
|
||||
Entry.group("edit", ModdedHelpMessages.GROUP_EDIT_OPEN_PACK_BIOME_REGION_AND_DIMENSION_JSON_FILES_IN_YOUR_DESKTOP_EDITOR),
|
||||
Entry.command("create", "<name> <pack|pack:dimensionKey> [seed]", ModdedHelpMessages.COMMAND_CREATE_CREATE_AND_INJECT_A_PERSISTENT_IRIS_DIMENSION_QUOTE_PACK_DIMENSIONKEY_TO_PICK),
|
||||
Entry.group("studio", ModdedHelpMessages.GROUP_STUDIO_PACK_PROJECT_CREATION_PACKAGING_AND_REPORTS, "std", "s"),
|
||||
Entry.group("pack", ModdedHelpMessages.GROUP_PACK_PACK_VALIDATION_AND_MAINTENANCE, "pk"),
|
||||
Entry.group("world", ModdedHelpMessages.GROUP_WORLD_RUNTIME_IRIS_DIMENSION_CREATION_REMOVAL_AND_STATUS, "w"),
|
||||
Entry.group("datapack", ModdedHelpMessages.GROUP_DATAPACK_WORLD_DATAPACK_INSTALL_AND_STATUS_HELPERS, "datapacks", "dp"),
|
||||
Entry.group("structure", ModdedHelpMessages.GROUP_STRUCTURE_IRIS_STRUCTURE_INDEX_INFO_AND_PLACEMENT_TOOLS, "struct", "str"),
|
||||
Entry.command("goldenhash", "[radius] [threads] [capture|verify]", ModdedHelpMessages.COMMAND_GOLDENHASH_GENERATE_DETERMINISTIC_BLOCK_HASHES_FOR_PARITY_TESTING, "gold"),
|
||||
Entry.group("developer", ModdedHelpMessages.GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_SENTRY_TEST_NETWORK_INTERFACES_REGION_FILE_SCAN, "dev")
|
||||
));
|
||||
SECTIONS.put("find", List.of(
|
||||
Entry.command("biome", "<key>", "Find an Iris biome"),
|
||||
Entry.command("region", "<key>", "Find an Iris region"),
|
||||
Entry.command("object", "<key>", "Find an object placement"),
|
||||
Entry.command("structure", "<key>", "Find an Iris-placed or native/datapack structure"),
|
||||
Entry.command("poi", "<type>", "Find a supported point of interest")
|
||||
Entry.command("biome", "<key>", ModdedHelpMessages.COMMAND_BIOME_FIND_AN_IRIS_BIOME),
|
||||
Entry.command("region", "<key>", ModdedHelpMessages.COMMAND_REGION_FIND_AN_IRIS_REGION),
|
||||
Entry.command("object", "<key>", ModdedHelpMessages.COMMAND_OBJECT_FIND_AN_OBJECT_PLACEMENT),
|
||||
Entry.command("structure", "<key>", ModdedHelpMessages.COMMAND_STRUCTURE_FIND_AN_IRIS_PLACED_OR_NATIVE_DATAPACK_STRUCTURE),
|
||||
Entry.command("poi", "<type>", ModdedHelpMessages.COMMAND_POI_FIND_A_SUPPORTED_POINT_OF_INTEREST)
|
||||
));
|
||||
SECTIONS.put("goto", SECTIONS.get("find"));
|
||||
SECTIONS.put("edit", List.of(
|
||||
Entry.command("biome", "[key]", "Open a biome json in your desktop editor; no key opens the biome at your position"),
|
||||
Entry.command("region", "[key]", "Open a region json in your desktop editor; no key opens the region at your position"),
|
||||
Entry.command("dimension", "", "Open the current pack's dimension json in your desktop editor")
|
||||
Entry.command("biome", "[key]", ModdedHelpMessages.COMMAND_BIOME_OPEN_A_BIOME_JSON_IN_YOUR_DESKTOP_EDITOR_NO_KEY_OPENS_THE),
|
||||
Entry.command("region", "[key]", ModdedHelpMessages.COMMAND_REGION_OPEN_A_REGION_JSON_IN_YOUR_DESKTOP_EDITOR_NO_KEY_OPENS_THE),
|
||||
Entry.command("dimension", "", ModdedHelpMessages.COMMAND_DIMENSION_OPEN_THE_CURRENT_PACK_S_DIMENSION_JSON_IN_YOUR_DESKTOP_EDITOR)
|
||||
));
|
||||
SECTIONS.put("pregen", List.of(
|
||||
Entry.command("start", "<radius> [dimension] [at] [x] [z] [gui] [sync] [nocache]", "Start pregeneration; radius in blocks, resumable checkpoint cache on by default, center via 'at <x> <z>', flags compose in any order"),
|
||||
Entry.command("stop", "", "Stop the active pregeneration task", "x"),
|
||||
Entry.command("pause", "", "Pause or resume pregeneration", "resume"),
|
||||
Entry.command("status", "", "Show pregeneration status")
|
||||
Entry.command("start", "<radius> [dimension] [at] [x] [z] [gui] [sync] [nocache]", ModdedHelpMessages.COMMAND_START_START_PREGENERATION_RADIUS_IN_BLOCKS_RESUMABLE_CHECKPOINT_CACHE_ON_BY_DEFAULT_CENTER),
|
||||
Entry.command("stop", "", ModdedHelpMessages.COMMAND_STOP_STOP_THE_ACTIVE_PREGENERATION_TASK, "x"),
|
||||
Entry.command("pause", "", ModdedHelpMessages.COMMAND_PAUSE_PAUSE_OR_RESUME_PREGENERATION, "resume"),
|
||||
Entry.command("status", "", ModdedHelpMessages.COMMAND_STATUS_SHOW_PREGENERATION_STATUS)
|
||||
));
|
||||
SECTIONS.put("pregenerate", SECTIONS.get("pregen"));
|
||||
SECTIONS.put("object", List.of(
|
||||
Entry.command("wand", "", "Get an Iris object wand"),
|
||||
Entry.command("dust", "", "Get dust that reveals object placements", "d"),
|
||||
Entry.command("save", "[overwrite] <name>", "Save the selected wand volume as an object"),
|
||||
Entry.command("paste", "[at] [x] [y] [z] [rotate] [degrees] <key>", "Paste an object at your position or a given position, optionally rotated"),
|
||||
Entry.command("expand", "[amount]", "Expand the wand selection in your looking direction"),
|
||||
Entry.command("contract", "[amount]", "Contract the wand selection in your looking direction", "-"),
|
||||
Entry.command("shift", "[amount]", "Shift the wand selection in your looking direction"),
|
||||
Entry.command("position1", "[look]", "Set selection point 1", "p1"),
|
||||
Entry.command("position2", "[look]", "Set selection point 2", "p2"),
|
||||
Entry.command("x+y", "", "Autoselect up and out", "xpy"),
|
||||
Entry.command("x&y", "", "Autoselect up, down and out", "xay"),
|
||||
Entry.command("analyze", "<key>", "Show object composition"),
|
||||
Entry.command("shrink", "<key>", "Shrink an object to its minimum size"),
|
||||
Entry.command("plausibilize", "<key|prefix/> [dryrun=true] [reach=N]", "Grow branches so tree leaves survive vanilla decay"),
|
||||
Entry.command("undo", "[amount]", "Undo pasted objects", "u")
|
||||
Entry.command("wand", "", ModdedHelpMessages.COMMAND_WAND_GET_AN_IRIS_OBJECT_WAND_2),
|
||||
Entry.command("dust", "", ModdedHelpMessages.COMMAND_DUST_GET_DUST_THAT_REVEALS_OBJECT_PLACEMENTS, "d"),
|
||||
Entry.command("save", "[overwrite] <name>", ModdedHelpMessages.COMMAND_SAVE_SAVE_THE_SELECTED_WAND_VOLUME_AS_AN_OBJECT),
|
||||
Entry.command("paste", "[at] [x] [y] [z] [rotate] [degrees] <key>", ModdedHelpMessages.COMMAND_PASTE_PASTE_AN_OBJECT_AT_YOUR_POSITION_OR_A_GIVEN_POSITION_OPTIONALLY_ROTATED),
|
||||
Entry.command("expand", "[amount]", ModdedHelpMessages.COMMAND_EXPAND_EXPAND_THE_WAND_SELECTION_IN_YOUR_LOOKING_DIRECTION),
|
||||
Entry.command("contract", "[amount]", ModdedHelpMessages.COMMAND_CONTRACT_CONTRACT_THE_WAND_SELECTION_IN_YOUR_LOOKING_DIRECTION, "-"),
|
||||
Entry.command("shift", "[amount]", ModdedHelpMessages.COMMAND_SHIFT_SHIFT_THE_WAND_SELECTION_IN_YOUR_LOOKING_DIRECTION),
|
||||
Entry.command("position1", "[look]", ModdedHelpMessages.COMMAND_POSITION1_SET_SELECTION_POINT_1, "p1"),
|
||||
Entry.command("position2", "[look]", ModdedHelpMessages.COMMAND_POSITION2_SET_SELECTION_POINT_2, "p2"),
|
||||
Entry.command("x+y", "", ModdedHelpMessages.COMMAND_X_Y_AUTOSELECT_UP_AND_OUT, "xpy"),
|
||||
Entry.command("x&y", "", ModdedHelpMessages.COMMAND_X_Y_AUTOSELECT_UP_DOWN_AND_OUT, "xay"),
|
||||
Entry.command("analyze", "<key>", ModdedHelpMessages.COMMAND_ANALYZE_SHOW_OBJECT_COMPOSITION),
|
||||
Entry.command("shrink", "<key>", ModdedHelpMessages.COMMAND_SHRINK_SHRINK_AN_OBJECT_TO_ITS_MINIMUM_SIZE),
|
||||
Entry.command("plausibilize", "<key|prefix/> [dryrun=true] [reach=N]", ModdedHelpMessages.COMMAND_PLAUSIBILIZE_GROW_BRANCHES_SO_TREE_LEAVES_SURVIVE_VANILLA_DECAY),
|
||||
Entry.command("undo", "[amount]", ModdedHelpMessages.COMMAND_UNDO_UNDO_PASTED_OBJECTS, "u")
|
||||
));
|
||||
SECTIONS.put("o", SECTIONS.get("object"));
|
||||
SECTIONS.put("studio", List.of(
|
||||
Entry.command("create", "<name> [template]", "Create a new pack project", "+"),
|
||||
Entry.command("package", "[pack]", "Package a dimension into a compressed format"),
|
||||
Entry.command("version", "[pack]", "Print a pack version"),
|
||||
Entry.command("regions", "[radius]", "Calculate nearby region distribution"),
|
||||
Entry.command("open", "<pack> [seed]", "Open a temporary studio dimension for a pack", "o"),
|
||||
Entry.command("close", "", "Close the open studio dimension and discard its world", "x"),
|
||||
Entry.command("tpstudio", "", "Teleport into the open studio dimension", "stp"),
|
||||
Entry.command("status", "", "Show the open studio dimension and its pack"),
|
||||
Entry.command("noise", "[generator] [seed]", "Open the Noise Explorer GUI on the server display", "nmap"),
|
||||
Entry.command("map", "", "Open the Vision map GUI on the server display", "render"),
|
||||
Entry.command("vscode", "[pack]", "Regenerate the .code-workspace for a pack and open it in your desktop editor", "vsc"),
|
||||
Entry.command("update", "[pack]", "Regenerate the .code-workspace for a pack"),
|
||||
Entry.command("importvanilla", "", "Explain vanilla import workflow", "importv", "iv")
|
||||
Entry.command("create", "<name> [template]", ModdedHelpMessages.COMMAND_CREATE_CREATE_A_NEW_PACK_PROJECT, "+"),
|
||||
Entry.command("package", "[pack]", ModdedHelpMessages.COMMAND_PACKAGE_PACKAGE_A_DIMENSION_INTO_A_COMPRESSED_FORMAT),
|
||||
Entry.command("version", "[pack]", ModdedHelpMessages.COMMAND_VERSION_PRINT_A_PACK_VERSION),
|
||||
Entry.command("regions", "[radius]", ModdedHelpMessages.COMMAND_REGIONS_CALCULATE_NEARBY_REGION_DISTRIBUTION),
|
||||
Entry.command("open", "<pack> [seed]", ModdedHelpMessages.COMMAND_OPEN_OPEN_A_TEMPORARY_STUDIO_DIMENSION_FOR_A_PACK, "o"),
|
||||
Entry.command("close", "", ModdedHelpMessages.COMMAND_CLOSE_CLOSE_THE_OPEN_STUDIO_DIMENSION_AND_DISCARD_ITS_WORLD, "x"),
|
||||
Entry.command("tpstudio", "", ModdedHelpMessages.COMMAND_TPSTUDIO_TELEPORT_INTO_THE_OPEN_STUDIO_DIMENSION, "stp"),
|
||||
Entry.command("status", "", ModdedHelpMessages.COMMAND_STATUS_SHOW_THE_OPEN_STUDIO_DIMENSION_AND_ITS_PACK),
|
||||
Entry.command("noise", "[generator] [seed]", ModdedHelpMessages.COMMAND_NOISE_OPEN_THE_NOISE_EXPLORER_GUI_ON_THE_SERVER_DISPLAY, "nmap"),
|
||||
Entry.command("map", "", ModdedHelpMessages.COMMAND_MAP_OPEN_THE_VISION_MAP_GUI_ON_THE_SERVER_DISPLAY, "render"),
|
||||
Entry.command("vscode", "[pack]", ModdedHelpMessages.COMMAND_VSCODE_REGENERATE_THE_CODE_WORKSPACE_FOR_A_PACK_AND_OPEN_IT_IN_YOUR, "vsc"),
|
||||
Entry.command("update", "[pack]", ModdedHelpMessages.COMMAND_UPDATE_REGENERATE_THE_CODE_WORKSPACE_FOR_A_PACK),
|
||||
Entry.command("importvanilla", "", ModdedHelpMessages.COMMAND_IMPORTVANILLA_EXPLAIN_VANILLA_IMPORT_WORKFLOW, "importv", "iv")
|
||||
));
|
||||
SECTIONS.put("std", SECTIONS.get("studio"));
|
||||
SECTIONS.put("s", SECTIONS.get("studio"));
|
||||
SECTIONS.put("pack", List.of(
|
||||
Entry.command("validate", "[pack]", "Validate a pack or every pack", "v"),
|
||||
Entry.command("cleanup", "<pack> [apply]", "Preview or quarantine unused-resource candidates", "c"),
|
||||
Entry.command("restore", "<pack> [apply]", "Preview or restore the latest quarantine", "r"),
|
||||
Entry.command("status", "[pack]", "Show cached validation status", "s")
|
||||
Entry.command("validate", "[pack]", ModdedHelpMessages.COMMAND_VALIDATE_VALIDATE_A_PACK_OR_EVERY_PACK, "v"),
|
||||
Entry.command("cleanup", "<pack> [apply]", ModdedHelpMessages.COMMAND_CLEANUP_PREVIEW_OR_QUARANTINE_UNUSED_RESOURCE_CANDIDATES, "c"),
|
||||
Entry.command("restore", "<pack> [apply]", ModdedHelpMessages.COMMAND_RESTORE_PREVIEW_OR_RESTORE_THE_LATEST_QUARANTINE, "r"),
|
||||
Entry.command("status", "[pack]", ModdedHelpMessages.COMMAND_STATUS_SHOW_CACHED_VALIDATION_STATUS, "s")
|
||||
));
|
||||
SECTIONS.put("pk", SECTIONS.get("pack"));
|
||||
SECTIONS.put("world", List.of(
|
||||
Entry.command("enable", "<dimension> <pack|pack:dimensionKey> [seed|random]", "Create and inject a persistent Iris dimension at runtime; downloads the pack if missing, quote pack:dimensionKey to pick a specific pack dimension", "create"),
|
||||
Entry.command("replace-overworld", "<pack|pack:dimensionKey> [seed|random]", "Inject an Iris primary world and route players there instead of the vanilla overworld"),
|
||||
Entry.command("disable", "<dimension>", "Evacuate and unload an Iris dimension; world data on disk is kept for re-enabling"),
|
||||
Entry.command("delete", "<dimension>", "Disable an Iris dimension and wipe its chunk and mantle data from disk", "remove", "rm"),
|
||||
Entry.command("list", "", "List loaded Iris dimensions", "ls"),
|
||||
Entry.command("status", "", "Show loaded Iris dimensions and the configured primary world")
|
||||
Entry.command("enable", "<dimension> <pack|pack:dimensionKey> [seed|random]", ModdedHelpMessages.COMMAND_ENABLE_CREATE_AND_INJECT_A_PERSISTENT_IRIS_DIMENSION_AT_RUNTIME_DOWNLOADS_THE_PACK, "create"),
|
||||
Entry.command("replace-overworld", "<pack|pack:dimensionKey> [seed|random]", ModdedHelpMessages.COMMAND_REPLACE_OVERWORLD_INJECT_AN_IRIS_PRIMARY_WORLD_AND_ROUTE_PLAYERS_THERE_INSTEAD_OF_THE),
|
||||
Entry.command("disable", "<dimension>", ModdedHelpMessages.COMMAND_DISABLE_EVACUATE_AND_UNLOAD_AN_IRIS_DIMENSION_WORLD_DATA_ON_DISK_IS_KEPT),
|
||||
Entry.command("delete", "<dimension>", ModdedHelpMessages.COMMAND_DELETE_DISABLE_AN_IRIS_DIMENSION_AND_WIPE_ITS_CHUNK_AND_MANTLE_DATA_FROM, "remove", "rm"),
|
||||
Entry.command("list", "", ModdedHelpMessages.COMMAND_LIST_LIST_LOADED_IRIS_DIMENSIONS, "ls"),
|
||||
Entry.command("status", "", ModdedHelpMessages.COMMAND_STATUS_SHOW_LOADED_IRIS_DIMENSIONS_AND_THE_CONFIGURED_PRIMARY_WORLD)
|
||||
));
|
||||
SECTIONS.put("w", SECTIONS.get("world"));
|
||||
SECTIONS.put("datapack", List.of(
|
||||
Entry.command("status", "", "Check loaded Iris dimension type overrides"),
|
||||
Entry.command("install", "", "Install dimension type overrides for loaded Iris dimensions"),
|
||||
Entry.command("list", "", "List configured and installed datapacks", "ls"),
|
||||
Entry.command("ingest", "", "Explain Bukkit datapack ingest workflow", "pull"),
|
||||
Entry.command("remove", "<id>", "Explain datapack removal workflow", "rm")
|
||||
Entry.command("status", "", ModdedHelpMessages.COMMAND_STATUS_CHECK_LOADED_IRIS_DIMENSION_TYPE_OVERRIDES),
|
||||
Entry.command("install", "", ModdedHelpMessages.COMMAND_INSTALL_INSTALL_DIMENSION_TYPE_OVERRIDES_FOR_LOADED_IRIS_DIMENSIONS),
|
||||
Entry.command("list", "", ModdedHelpMessages.COMMAND_LIST_LIST_CONFIGURED_AND_INSTALLED_DATAPACKS, "ls"),
|
||||
Entry.command("ingest", "", ModdedHelpMessages.COMMAND_INGEST_EXPLAIN_BUKKIT_DATAPACK_INGEST_WORKFLOW, "pull"),
|
||||
Entry.command("remove", "<id>", ModdedHelpMessages.COMMAND_REMOVE_EXPLAIN_DATAPACK_REMOVAL_WORKFLOW, "rm")
|
||||
));
|
||||
SECTIONS.put("datapacks", SECTIONS.get("datapack"));
|
||||
SECTIONS.put("dp", SECTIONS.get("datapack"));
|
||||
SECTIONS.put("structure", List.of(
|
||||
Entry.command("list", "", "Regenerate structure-index.json", "ls"),
|
||||
Entry.command("info", "<key>", "Resolve an Iris structure graph and report bounds"),
|
||||
Entry.command("place", "<key>", "Assemble and place an Iris structure at your location", "p"),
|
||||
Entry.command("import", "", "Explain Bukkit structure import workflow", "import-all", "reimport", "imp", "all"),
|
||||
Entry.command("capture", "", "Explain Bukkit structure capture workflow", "cap"),
|
||||
Entry.command("verify", "[key]", "Report native and Iris structure reachability in the current dimension", "locateall")
|
||||
Entry.command("list", "", ModdedHelpMessages.COMMAND_LIST_REGENERATE_STRUCTURE_INDEX_JSON, "ls"),
|
||||
Entry.command("info", "<key>", ModdedHelpMessages.COMMAND_INFO_RESOLVE_AN_IRIS_STRUCTURE_GRAPH_AND_REPORT_BOUNDS),
|
||||
Entry.command("place", "<key>", ModdedHelpMessages.COMMAND_PLACE_ASSEMBLE_AND_PLACE_AN_IRIS_STRUCTURE_AT_YOUR_LOCATION, "p"),
|
||||
Entry.command("import", "", ModdedHelpMessages.COMMAND_IMPORT_EXPLAIN_BUKKIT_STRUCTURE_IMPORT_WORKFLOW, "import-all", "reimport", "imp", "all"),
|
||||
Entry.command("capture", "", ModdedHelpMessages.COMMAND_CAPTURE_EXPLAIN_BUKKIT_STRUCTURE_CAPTURE_WORKFLOW, "cap"),
|
||||
Entry.command("verify", "[key]", ModdedHelpMessages.COMMAND_VERIFY_REPORT_NATIVE_AND_IRIS_STRUCTURE_REACHABILITY_IN_THE_CURRENT_DIMENSION, "locateall")
|
||||
));
|
||||
SECTIONS.put("struct", SECTIONS.get("structure"));
|
||||
SECTIONS.put("str", SECTIONS.get("structure"));
|
||||
SECTIONS.put("developer", List.of(
|
||||
Entry.command("sentry", "", "Send a test exception to the Iris error reporter"),
|
||||
Entry.command("network", "", "List network interfaces and their addresses", "ip")
|
||||
Entry.command("sentry", "", ModdedHelpMessages.COMMAND_SENTRY_SEND_A_TEST_EXCEPTION_TO_THE_IRIS_ERROR_REPORTER),
|
||||
Entry.command("network", "", ModdedHelpMessages.COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES, "ip")
|
||||
));
|
||||
SECTIONS.put("dev", SECTIONS.get("developer"));
|
||||
}
|
||||
@@ -179,7 +185,10 @@ final class ModdedCommandHelp {
|
||||
String normalized = normalize(path);
|
||||
List<Entry> entries = SECTIONS.get(normalized);
|
||||
if (entries == null) {
|
||||
ModdedCommandFeedback.fail(source, "Unknown Iris help section: " + normalized);
|
||||
ModdedCommandFeedback.fail(source, IrisLanguage.plain(
|
||||
IrisMessages.MODDED_HELP_UNKNOWN_SECTION,
|
||||
MessageArgument.untrusted("section", normalized)
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -208,9 +217,11 @@ final class ModdedCommandHelp {
|
||||
String parent = parentPath(path);
|
||||
String command = parent.isEmpty() ? "/iris" : "/iris help " + parent;
|
||||
MutableComponent hover = Component.empty()
|
||||
.append(text("Click to go back to ", DARK_GREEN))
|
||||
.append(text(parent.isEmpty() ? "Iris" : parent, PARAMETER_ALT));
|
||||
return text("〈 Back", BACK).withStyle((style) -> style
|
||||
.append(text(IrisLanguage.plain(
|
||||
IrisMessages.MODDED_HELP_BACK_HOVER,
|
||||
MessageArgument.untrusted("parent", parent.isEmpty() ? "Iris" : parent)
|
||||
), DARK_GREEN));
|
||||
return text("〈 " + IrisLanguage.plain(DirectorHelpMessages.BACK), BACK).withStyle((style) -> style
|
||||
.withClickEvent(new ClickEvent.RunCommand(command))
|
||||
.withHoverEvent(new HoverEvent.ShowText(hover)));
|
||||
}
|
||||
@@ -239,7 +250,7 @@ final class ModdedCommandHelp {
|
||||
|
||||
private static MutableComponent nodes(Entry entry) {
|
||||
if (entry.group()) {
|
||||
return text(" - Category of Commands", CATEGORY);
|
||||
return text(" - " + IrisLanguage.plain(DirectorHelpMessages.COMMAND_GROUP), CATEGORY);
|
||||
}
|
||||
|
||||
List<String> tokens = usageTokens(entry.usage());
|
||||
@@ -273,18 +284,18 @@ final class ModdedCommandHelp {
|
||||
hover.append(text(name, PARAMETER));
|
||||
hover.append(Component.literal("\n"));
|
||||
hover.append(text("✎ ", DESCRIPTION_ICON));
|
||||
hover.append(text("Command parameter", DESCRIPTION));
|
||||
hover.append(text(IrisLanguage.plain(IrisMessages.MODDED_HELP_COMMAND_PARAMETER), DESCRIPTION));
|
||||
hover.append(Component.literal("\n"));
|
||||
if (required) {
|
||||
hover.append(text("⚠ ", REQUIRED));
|
||||
hover.append(text("This parameter is required.", REQUIRED_TEXT));
|
||||
hover.append(text(IrisLanguage.plain(IrisMessages.MODDED_HELP_PARAMETER_REQUIRED), REQUIRED_TEXT));
|
||||
} else {
|
||||
hover.append(text("✔ ", DESCRIPTION_ICON));
|
||||
hover.append(text("This parameter is optional.", USAGE));
|
||||
hover.append(text(IrisLanguage.plain(IrisMessages.MODDED_HELP_PARAMETER_OPTIONAL), USAGE));
|
||||
}
|
||||
hover.append(Component.literal("\n"));
|
||||
hover.append(text("✢ ", DARK_GREEN));
|
||||
hover.append(text("This parameter is read as text by Brigadier.", HOVER_TYPE));
|
||||
hover.append(text(IrisLanguage.plain(IrisMessages.MODDED_HELP_BRIGADIER_TEXT), HOVER_TYPE));
|
||||
|
||||
return title.withStyle((style) -> style.withHoverEvent(new HoverEvent.ShowText(hover)));
|
||||
}
|
||||
@@ -294,15 +305,15 @@ final class ModdedCommandHelp {
|
||||
hover.append(text(names(entry), PARAMETER));
|
||||
hover.append(Component.literal("\n"));
|
||||
hover.append(text("✎ ", DESCRIPTION_ICON));
|
||||
hover.append(text(entry.description(), DESCRIPTION));
|
||||
hover.append(text(IrisLanguage.plain(entry.description()), DESCRIPTION));
|
||||
hover.append(Component.literal("\n"));
|
||||
hover.append(text("✒ ", USAGE_ICON));
|
||||
if (entry.group()) {
|
||||
hover.append(text("This is a command category. Click to run.", USAGE));
|
||||
hover.append(text(IrisLanguage.plain(DirectorHelpMessages.COMMAND_GROUP), USAGE));
|
||||
} else if (entry.usage().isBlank()) {
|
||||
hover.append(text("There are no parameters. Click to type command.", USAGE));
|
||||
hover.append(text(IrisLanguage.plain(DirectorHelpMessages.NO_PARAMETERS), USAGE));
|
||||
} else {
|
||||
hover.append(text("Hover over all of the parameters to learn more.", USAGE));
|
||||
hover.append(text(IrisLanguage.plain(DirectorHelpMessages.PARAMETERS), USAGE));
|
||||
hover.append(Component.literal("\n"));
|
||||
hover.append(text("✦ ", EXAMPLE_ICON));
|
||||
hover.append(text(suggestion, PARAMETER));
|
||||
@@ -311,7 +322,7 @@ final class ModdedCommandHelp {
|
||||
String parent = path.isEmpty() ? "/iris" : "/iris " + path;
|
||||
if (entry.aliases().length > 0) {
|
||||
hover.append(Component.literal("\n"));
|
||||
hover.append(text("Aliases: ", DARK_GREEN));
|
||||
hover.append(text(IrisLanguage.plain(DirectorHelpMessages.ALIASES) + ": ", DARK_GREEN));
|
||||
List<String> aliases = new ArrayList<>(entry.aliases().length);
|
||||
for (String alias : entry.aliases()) {
|
||||
aliases.add(parent + " " + alias);
|
||||
@@ -324,11 +335,11 @@ final class ModdedCommandHelp {
|
||||
private static MutableComponent opNotice() {
|
||||
MutableComponent notice = Component.empty();
|
||||
notice.append(text("⚠ ", REQUIRED));
|
||||
notice.append(text("Iris commands need operator permission (level 2). ", REQUIRED_TEXT));
|
||||
notice.append(text("Run ", DESCRIPTION));
|
||||
notice.append(text("/op <you>", PARAMETER_ALT));
|
||||
notice.append(text(" from the console (or enable cheats in singleplayer); ", DESCRIPTION));
|
||||
notice.append(text("until then these commands will not run or tab-complete.", USAGE));
|
||||
notice.append(text(IrisLanguage.plain(IrisMessages.MODDED_HELP_OPERATOR_NOTICE) + " ", REQUIRED_TEXT));
|
||||
notice.append(text(IrisLanguage.plain(
|
||||
IrisMessages.MODDED_HELP_OPERATOR_INSTRUCTION,
|
||||
MessageArgument.trusted("command", "/op <you>")
|
||||
), DESCRIPTION));
|
||||
return notice;
|
||||
}
|
||||
|
||||
@@ -404,12 +415,12 @@ final class ModdedCommandHelp {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private record Entry(String name, String usage, String description, boolean group, String... aliases) {
|
||||
static Entry command(String name, String usage, String description, String... aliases) {
|
||||
private record Entry(String name, String usage, TextKey description, boolean group, String... aliases) {
|
||||
static Entry command(String name, String usage, TextKey description, String... aliases) {
|
||||
return new Entry(name, usage, description, false, aliases);
|
||||
}
|
||||
|
||||
static Entry group(String name, String description, String... aliases) {
|
||||
static Entry group(String name, TextKey description, String... aliases) {
|
||||
return new Entry(name, "", description, true, aliases);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-22
@@ -45,6 +45,10 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class ModdedDatapackCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -118,8 +122,7 @@ public final class ModdedDatapackCommands {
|
||||
|
||||
Engine engine = IrisModdedCommands.engineFor(level);
|
||||
if (engine == null || engine.getDimension() == null) {
|
||||
IrisModdedCommands.ok(source, dimensionId + ": type=" + typeKey + " active=" + activeMin + ".." + activeMax
|
||||
+ " logical=" + active.logicalHeight() + " (pack=" + irisGenerator.dimensionKey() + ", engine not started; pack heights unknown)");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_TYPE_ACTIVE_LOGICAL_PACK_ENGINE_NOT_STARTED_PACK_HEIGHTS_UNKNOWN, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("typeKey", typeKey), MessageArgument.untrusted("activeMin", activeMin), MessageArgument.untrusted("activeMax", activeMax), MessageArgument.untrusted("value", active.logicalHeight()), MessageArgument.untrusted("value2", irisGenerator.dimensionKey())));
|
||||
continue;
|
||||
}
|
||||
IrisDimension dimension = engine.getDimension();
|
||||
@@ -128,22 +131,18 @@ public final class ModdedDatapackCommands {
|
||||
int packLogical = dimension.getLogicalHeight();
|
||||
boolean matches = packMin == activeMin && packMax == activeMax && packLogical == active.logicalHeight();
|
||||
File override = overrideFile(server, irisGenerator.dimensionKey());
|
||||
IrisModdedCommands.ok(source, dimensionId + ": type=" + typeKey
|
||||
+ " active=" + activeMin + ".." + activeMax + " logical=" + active.logicalHeight()
|
||||
+ " | pack '" + dimension.getLoadKey() + "' wants " + packMin + ".." + packMax + " logical=" + packLogical
|
||||
+ " | " + (matches ? "MATCH" : "MISMATCH")
|
||||
+ (override.isFile() ? " (world datapack override installed)" : ""));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_TYPE_ACTIVE_LOGICAL_PACK_WANTS_LOGICAL, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("typeKey", typeKey), MessageArgument.untrusted("activeMin", activeMin), MessageArgument.untrusted("activeMax", activeMax), MessageArgument.untrusted("value", active.logicalHeight()), MessageArgument.untrusted("value2", dimension.getLoadKey()), MessageArgument.untrusted("packMin", packMin), MessageArgument.untrusted("packMax", packMax), MessageArgument.untrusted("packLogical", packLogical), MessageArgument.trusted("value3", IrisLanguage.plain(matches ? RuntimeUiMessages.STATUS_MATCH : RuntimeUiMessages.STATUS_MISMATCH)), MessageArgument.trusted("value4", override.isFile() ? IrisLanguage.plain(RuntimeUiMessages.DATAPACK_OVERRIDE_SUFFIX) : "")));
|
||||
if (!matches) {
|
||||
mismatches++;
|
||||
IrisModdedCommands.fail(source, " WARNING: the active dimension type does not match the pack. Iris will refuse to start this world engine instead of clipping terrain. Run /iris world enable <dimension> <pack> for new worlds, or /iris datapack install for already-loaded Iris dimensions, then restart.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_WARNING_ACTIVE_DIMENSION_TYPE_DOES_NOT_MATCH_PACK_IRIS_WILL));
|
||||
}
|
||||
}
|
||||
if (irisLevels == 0) {
|
||||
IrisModdedCommands.fail(source, "No Iris dimensions are loaded.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_NO_IRIS_DIMENSIONS_ARE_LOADED));
|
||||
return 0;
|
||||
}
|
||||
if (mismatches == 0) {
|
||||
IrisModdedCommands.ok(source, "All " + irisLevels + " Iris dimension(s) match their pack height ranges.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_ALL_IRIS_DIMENSION_S_MATCH_THEIR_PACK_HEIGHT_RANGES, MessageArgument.untrusted("irisLevels", irisLevels)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -157,7 +156,7 @@ public final class ModdedDatapackCommands {
|
||||
}
|
||||
Engine engine = IrisModdedCommands.engineFor(level);
|
||||
if (engine == null || engine.getDimension() == null) {
|
||||
IrisModdedCommands.fail(source, level.dimension().identifier() + ": engine not started; cannot derive its dimension type yet.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_ENGINE_NOT_STARTED_CANNOT_DERIVE_ITS_DIMENSION_TYPE_YET, MessageArgument.untrusted("value", level.dimension().identifier())));
|
||||
continue;
|
||||
}
|
||||
IrisDimension dimension = engine.getDimension();
|
||||
@@ -166,7 +165,7 @@ public final class ModdedDatapackCommands {
|
||||
json = dimension.getDimensionType().toJson(DataVersion.getLatest().get());
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris dimension type generation failed for {}", dimension.getLoadKey(), e);
|
||||
IrisModdedCommands.fail(source, level.dimension().identifier() + ": dimension type generation failed: " + e.getMessage());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_DIMENSION_TYPE_GENERATION_FAILED, MessageArgument.untrusted("value", level.dimension().identifier()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage()))));
|
||||
continue;
|
||||
}
|
||||
File output = overrideFile(server, irisGenerator.dimensionKey());
|
||||
@@ -176,11 +175,11 @@ public final class ModdedDatapackCommands {
|
||||
written.add(output.getPath());
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Iris dimension type write failed for {}", output, e);
|
||||
IrisModdedCommands.fail(source, "Failed to write " + output + ": " + e.getMessage());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_FAILED_WRITE, MessageArgument.untrusted("output", output), MessageArgument.untrusted("value", String.valueOf(e.getMessage()))));
|
||||
}
|
||||
}
|
||||
if (written.isEmpty()) {
|
||||
IrisModdedCommands.fail(source, "No Iris dimensions with running engines found; nothing was installed.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_NO_IRIS_DIMENSIONS_WITH_RUNNING_ENGINES_FOUND_NOTHING_WAS_INSTALLED));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -200,14 +199,14 @@ public final class ModdedDatapackCommands {
|
||||
written.add(mcmeta.getPath());
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Iris pack.mcmeta write failed for {}", mcmeta, e);
|
||||
IrisModdedCommands.fail(source, "Failed to write " + mcmeta + ": " + e.getMessage());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_FAILED_WRITE_2, MessageArgument.untrusted("mcmeta", mcmeta), MessageArgument.untrusted("value", String.valueOf(e.getMessage()))));
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (String path : written) {
|
||||
IrisModdedCommands.ok(source, "Wrote " + path);
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_WROTE, MessageArgument.untrusted("path", path)));
|
||||
}
|
||||
IrisModdedCommands.ok(source, "World datapack '" + WORLD_PACK_NAME + "' dimension type overrides installed. Restart the server for the dimension types to apply.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_WORLD_DATAPACK_DIMENSION_TYPE_OVERRIDES_INSTALLED_RESTART_SERVER_DIMENSION_TYPES, MessageArgument.untrusted("WORLDPACKNAME", WORLD_PACK_NAME)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -239,12 +238,12 @@ public final class ModdedDatapackCommands {
|
||||
}
|
||||
}
|
||||
|
||||
IrisModdedCommands.ok(source, "Configured datapack imports: " + configured.size());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_CONFIGURED_DATAPACK_IMPORTS, MessageArgument.untrusted("value", configured.size())));
|
||||
for (String url : configured) {
|
||||
IrisModdedCommands.ok(source, " - " + url);
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_MESSAGE, MessageArgument.untrusted("url", url)));
|
||||
}
|
||||
if (!configured.isEmpty()) {
|
||||
IrisModdedCommands.ok(source, "Modrinth ingest is Bukkit-only; install these manually into world/datapacks if needed.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_MODRINTH_INGEST_IS_BUKKIT_ONLY_INSTALL_THESE_MANUALLY_INTO_WORLD));
|
||||
}
|
||||
|
||||
File datapacks = worldDatapacksFolder(server);
|
||||
@@ -257,9 +256,9 @@ public final class ModdedDatapackCommands {
|
||||
}
|
||||
}
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Installed world datapacks: " + names.size());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_INSTALLED_WORLD_DATAPACKS, MessageArgument.untrusted("value", names.size())));
|
||||
for (String name : names) {
|
||||
IrisModdedCommands.ok(source, " - " + name);
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DATAPACK_COMMANDS_MESSAGE_2, MessageArgument.untrusted("name", name)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+6
-3
@@ -33,6 +33,9 @@ import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
final class ModdedDeveloperCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -53,7 +56,7 @@ final class ModdedDeveloperCommands {
|
||||
|
||||
private static int sentry(CommandSourceStack source) {
|
||||
IrisPlatforms.get().reportError(new Exception("This is an Iris Sentry test exception"));
|
||||
ModdedCommandFeedback.ok(source, "Dispatched a test exception to the Iris error reporter (Sentry if enabled).");
|
||||
ModdedCommandFeedback.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DEVELOPER_COMMANDS_DISPATCHED_TEST_EXCEPTION_IRIS_ERROR_REPORTER_SENTRY_IF_ENABLED));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -63,13 +66,13 @@ final class ModdedDeveloperCommands {
|
||||
for (NetworkInterface networkInterface : Collections.list(interfaces)) {
|
||||
ModdedCommandFeedback.ok(source, networkInterface.getDisplayName());
|
||||
for (InetAddress address : Collections.list(networkInterface.getInetAddresses())) {
|
||||
ModdedCommandFeedback.ok(source, " " + address.getHostAddress());
|
||||
ModdedCommandFeedback.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DEVELOPER_COMMANDS_MESSAGE, MessageArgument.untrusted("value", address.getHostAddress())));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
} catch (SocketException error) {
|
||||
LOGGER.error("Iris developer network dump failed", error);
|
||||
ModdedCommandFeedback.fail(source, "Network scan failed: " + error.getClass().getSimpleName());
|
||||
ModdedCommandFeedback.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DEVELOPER_COMMANDS_NETWORK_SCAN_FAILED, MessageArgument.untrusted("value", error.getClass().getSimpleName())));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+65
-15
@@ -18,10 +18,13 @@
|
||||
|
||||
package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.modded.ModdedBlockState;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.DustParticleOptions;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -50,7 +53,7 @@ public final class ModdedDustRevealer {
|
||||
public static void reveal(ServerPlayer player, ServerLevel level, BlockPos pos) {
|
||||
Engine engine = IrisModdedCommands.engineFor(level);
|
||||
if (engine == null) {
|
||||
player.sendSystemMessage(Component.literal("This dimension is not generated by Iris."));
|
||||
player.sendSystemMessage(Component.literal(IrisLanguage.plain(RuntimeUiMessages.DUST_IRIS_WORLD_REQUIRED)));
|
||||
return;
|
||||
}
|
||||
describe(player, level, engine, pos);
|
||||
@@ -60,7 +63,10 @@ public final class ModdedDustRevealer {
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
player.sendSystemMessage(Component.literal("Found object " + key));
|
||||
player.sendSystemMessage(Component.literal(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_FOUND_OBJECT,
|
||||
MessageArgument.untrusted("object", key)
|
||||
)));
|
||||
MinecraftServer server = level.getServer();
|
||||
BlockPos origin = pos.immutable();
|
||||
Thread thread = new Thread(() -> {
|
||||
@@ -71,8 +77,11 @@ public final class ModdedDustRevealer {
|
||||
hit.getX() + 0.5D, hit.getY() + 0.5D, hit.getZ() + 0.5D,
|
||||
3, 0.25D, 0.25D, 0.25D, 0.0D);
|
||||
}
|
||||
player.sendSystemMessage(Component.literal("Revealed " + hits.size() + " block(s) of " + key
|
||||
+ (hits.size() >= MAX_HITS ? " (capped)" : "")));
|
||||
player.sendSystemMessage(Component.literal(IrisLanguage.plain(
|
||||
hits.size() >= MAX_HITS ? RuntimeUiMessages.DUST_REVEALED_CAPPED : RuntimeUiMessages.DUST_REVEALED,
|
||||
MessageArgument.trusted("count", hits.size()),
|
||||
MessageArgument.untrusted("object", key)
|
||||
)));
|
||||
});
|
||||
}, "Iris Dust Revealer");
|
||||
thread.setDaemon(true);
|
||||
@@ -133,31 +142,72 @@ public final class ModdedDustRevealer {
|
||||
IrisRegion region = safe(() -> engine.getRegion(x, z));
|
||||
|
||||
List<String> lines = new ArrayList<>();
|
||||
lines.add("--- Iris Dust @ " + x + ", " + y + ", " + z + " ---");
|
||||
lines.add("Block: " + ModdedBlockState.serialize(level.getBlockState(pos)));
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_HEADER,
|
||||
MessageArgument.trusted("x", x),
|
||||
MessageArgument.trusted("y", y),
|
||||
MessageArgument.trusted("z", z)
|
||||
));
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_BLOCK,
|
||||
MessageArgument.untrusted("block", ModdedBlockState.serialize(level.getBlockState(pos)))
|
||||
));
|
||||
if (offset > 0) {
|
||||
lines.add("Position: +" + offset + " ABOVE surface (surface Y=" + surfaceY + ")");
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_POSITION_ABOVE,
|
||||
MessageArgument.trusted("offset", offset),
|
||||
MessageArgument.trusted("surfaceY", surfaceY)
|
||||
));
|
||||
} else if (offset < 0) {
|
||||
lines.add("Position: " + (-offset) + " below surface (surface Y=" + surfaceY + ")");
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_POSITION_BELOW,
|
||||
MessageArgument.trusted("offset", -offset),
|
||||
MessageArgument.trusted("surfaceY", surfaceY)
|
||||
));
|
||||
} else {
|
||||
lines.add("Position: at surface (Y=" + surfaceY + ")");
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_POSITION_AT,
|
||||
MessageArgument.trusted("surfaceY", surfaceY)
|
||||
));
|
||||
}
|
||||
lines.add("Object @block: " + (objectKey == null ? "none" : objectKey));
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_OBJECT_AT_BLOCK,
|
||||
MessageArgument.untrusted(
|
||||
"object",
|
||||
objectKey == null ? IrisLanguage.plain(RuntimeUiMessages.DUST_NONE) : objectKey
|
||||
)
|
||||
));
|
||||
if (surfaceBiome != null) {
|
||||
lines.add("Surface biome: " + surfaceBiome.getLoadKey());
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_SURFACE_BIOME,
|
||||
MessageArgument.untrusted("biome", surfaceBiome.getLoadKey())
|
||||
));
|
||||
}
|
||||
if (biomeHere != null && (surfaceBiome == null || !biomeHere.getLoadKey().equals(surfaceBiome.getLoadKey()))) {
|
||||
lines.add("Biome @Y: " + biomeHere.getLoadKey());
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_BIOME_AT_Y,
|
||||
MessageArgument.untrusted("biome", biomeHere.getLoadKey())
|
||||
));
|
||||
}
|
||||
if (caveBiome != null && (surfaceBiome == null || !caveBiome.getLoadKey().equals(surfaceBiome.getLoadKey()))) {
|
||||
lines.add("Cave/Mantle biome: " + caveBiome.getLoadKey());
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_CAVE_BIOME,
|
||||
MessageArgument.untrusted("biome", caveBiome.getLoadKey())
|
||||
));
|
||||
}
|
||||
if (region != null) {
|
||||
lines.add("Region: " + region.getLoadKey() + " (" + region.getName() + ")");
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_REGION,
|
||||
MessageArgument.untrusted("region", region.getLoadKey()),
|
||||
MessageArgument.untrusted("name", region.getName())
|
||||
));
|
||||
}
|
||||
Set<String> objects = safe(() -> engine.getObjectsAt(x >> 4, z >> 4));
|
||||
if (objects != null && !objects.isEmpty()) {
|
||||
lines.add("Objects in chunk: " + objects);
|
||||
lines.add(IrisLanguage.plain(
|
||||
RuntimeUiMessages.DUST_OBJECTS_IN_CHUNK,
|
||||
MessageArgument.untrusted("objects", objects)
|
||||
));
|
||||
}
|
||||
for (String line : lines) {
|
||||
player.sendSystemMessage(Component.literal(line));
|
||||
|
||||
+24
-4
@@ -36,6 +36,10 @@ import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.iris.core.localization.RuntimeProgressMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class ModdedGoldenHash {
|
||||
public enum Mode {
|
||||
AUTO,
|
||||
@@ -80,13 +84,18 @@ public final class ModdedGoldenHash {
|
||||
|
||||
public static void start(CommandSourceStack source, ServerLevel level, Engine engine, int radius, int threads, Mode mode) {
|
||||
if (!ACTIVE.compareAndSet(false, true)) {
|
||||
IrisModdedCommands.fail(source, "A goldenhash scan is already running.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_GOLDEN_HASH_GOLDENHASH_SCAN_IS_ALREADY_RUNNING));
|
||||
return;
|
||||
}
|
||||
ModdedGoldenHash scan = new ModdedGoldenHash(source, level, engine, radius, threads, mode);
|
||||
int boundedRadius = Math.max(0, radius);
|
||||
int chunks = (boundedRadius * 2 + 1) * (boundedRadius * 2 + 1);
|
||||
scan.ok("GoldenHash started: " + chunks + " chunk(s) around 0,0 in buffers (world untouched), threads=" + Math.max(1, threads) + " mode=" + mode);
|
||||
scan.ok(IrisLanguage.plain(
|
||||
RuntimeProgressMessages.GOLDEN_STARTED,
|
||||
MessageArgument.trusted("chunks", chunks),
|
||||
MessageArgument.trusted("threads", Math.max(1, threads)),
|
||||
MessageArgument.untrusted("mode", mode)
|
||||
));
|
||||
LOGGER.info("goldenhash start: dim={} seed={} radius={} threads={} mode={} file={}",
|
||||
engine.getDimension().getLoadKey(), engine.getSeedManager().getSeed(), boundedRadius, Math.max(1, threads), mode, scan.hashEngine.getGoldenFile().getName());
|
||||
Thread thread = new Thread(() -> {
|
||||
@@ -161,14 +170,25 @@ public final class ModdedGoldenHash {
|
||||
int doneCount = hashed.incrementAndGet();
|
||||
int stride = total <= 64 ? 1 : 32;
|
||||
if (doneCount % stride == 0 || doneCount == total) {
|
||||
ModdedGoldenHash.this.ok("[" + doneCount + "/" + total + "] chunk " + chunkX + "," + chunkZ + " hashed");
|
||||
ModdedGoldenHash.this.ok(IrisLanguage.plain(
|
||||
RuntimeProgressMessages.GOLDEN_CHUNK_HASHED,
|
||||
MessageArgument.trusted("done", doneCount),
|
||||
MessageArgument.trusted("total", total),
|
||||
MessageArgument.trusted("x", chunkX),
|
||||
MessageArgument.trusted("z", chunkZ)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkFailed(int chunkX, int chunkZ, Throwable error) {
|
||||
LOGGER.error("goldenhash chunk {},{} failed", chunkX, chunkZ, error);
|
||||
ModdedGoldenHash.this.fail("Chunk " + chunkX + "," + chunkZ + " FAILED: " + error.getClass().getSimpleName());
|
||||
ModdedGoldenHash.this.fail(IrisLanguage.plain(
|
||||
RuntimeProgressMessages.GOLDEN_CHUNK_FAILED,
|
||||
MessageArgument.trusted("x", chunkX),
|
||||
MessageArgument.trusted("z", chunkZ),
|
||||
MessageArgument.untrusted("type", error.getClass().getSimpleName())
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+60
-55
@@ -69,6 +69,10 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class ModdedObjectCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -218,55 +222,55 @@ public final class ModdedObjectCommands {
|
||||
public static int giveWand(CommandSourceStack source) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players. (the wand is a physical item)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_WAND_IS));
|
||||
return 0;
|
||||
}
|
||||
if (!player.getInventory().add(ModdedWandService.createWand())) {
|
||||
IrisModdedCommands.fail(source, "Your inventory is full.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_YOUR_INVENTORY_IS_FULL));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Poof! Good luck building! (left click = corner 1, right click = corner 2)");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_POOF_GOOD_LUCK_BUILDING_LEFT_CLICK_CORNER_1_RIGHT_CLICK));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int giveDust(CommandSourceStack source) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players. (the dust is a physical item)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_DUST_IS));
|
||||
return 0;
|
||||
}
|
||||
if (!player.getInventory().add(ModdedWandService.createDust())) {
|
||||
IrisModdedCommands.fail(source, "Your inventory is full.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_YOUR_INVENTORY_IS_FULL_2));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Right click a block to reveal the object it belongs to.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_RIGHT_CLICK_BLOCK_REVEAL_OBJECT_IT_BELONGS));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int save(CommandSourceStack source, String nameRaw, boolean overwrite) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players. (saving captures your wand selection)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_SAVING_CAPTURES));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = player.level();
|
||||
Engine engine = IrisModdedCommands.engineFor(level);
|
||||
if (engine == null) {
|
||||
IrisModdedCommands.fail(source, "This dimension is not generated by Iris; objects save into the dimension's pack.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_OBJECTS_SAVE_INTO));
|
||||
return 0;
|
||||
}
|
||||
if (!ModdedWandService.isHoldingWand(player)) {
|
||||
IrisModdedCommands.fail(source, "Hold your Iris wand. (/iris wand)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_HOLD_YOUR_IRIS_WAND_IRIS_WAND));
|
||||
return 0;
|
||||
}
|
||||
ModdedWandService.Selection selection = ModdedWandService.selection(player);
|
||||
if (selection == null) {
|
||||
IrisModdedCommands.fail(source, "No area selected. Left/right click blocks with the wand first.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_NO_AREA_SELECTED_LEFT_RIGHT_CLICK_BLOCKS_WITH_WAND_FIRST));
|
||||
return 0;
|
||||
}
|
||||
String name = nameRaw.trim().replace('\\', '/');
|
||||
if (name.isEmpty() || name.contains("..")) {
|
||||
IrisModdedCommands.fail(source, "Invalid object name: " + nameRaw);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_INVALID_OBJECT_NAME, MessageArgument.untrusted("nameRaw", nameRaw)));
|
||||
return 0;
|
||||
}
|
||||
BlockPos min = selection.min();
|
||||
@@ -276,12 +280,12 @@ public final class ModdedObjectCommands {
|
||||
int d = max.getZ() - min.getZ() + 1;
|
||||
long volume = (long) w * h * d;
|
||||
if (volume > MAX_SAVE_VOLUME) {
|
||||
IrisModdedCommands.fail(source, "Selection too large: " + volume + " blocks (max " + MAX_SAVE_VOLUME + ").");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_SELECTION_TOO_LARGE_BLOCKS_MAX, MessageArgument.untrusted("volume", volume), MessageArgument.untrusted("MAXSAVEVOLUME", MAX_SAVE_VOLUME)));
|
||||
return 0;
|
||||
}
|
||||
File file = new File(engine.getData().getDataFolder(), "objects" + File.separator + name.replace('/', File.separatorChar) + ".iob");
|
||||
if (file.exists() && !overwrite) {
|
||||
IrisModdedCommands.fail(source, "File already exists. Use /iris object save overwrite " + name);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_FILE_ALREADY_EXISTS_USE_IRIS_OBJECT_SAVE_OVERWRITE, MessageArgument.untrusted("name", name)));
|
||||
return 0;
|
||||
}
|
||||
int[] tilesSkipped = {0};
|
||||
@@ -295,7 +299,7 @@ public final class ModdedObjectCommands {
|
||||
object.write(file);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Iris object save failed for {}", file.getAbsolutePath(), e);
|
||||
IrisModdedCommands.fail(source, "Failed to save object: " + e.getMessage());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_FAILED_SAVE_OBJECT, MessageArgument.untrusted("value", String.valueOf(e.getMessage()))));
|
||||
return 0;
|
||||
}
|
||||
StringBuilder tileNote = new StringBuilder();
|
||||
@@ -308,8 +312,7 @@ public final class ModdedObjectCommands {
|
||||
} else if (tilesSkipped[0] > 0) {
|
||||
tileNote.append(" (").append(tilesSkipped[0]).append(" tile state(s) could not be captured)");
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Saved " + engine.getData().getDataFolder().getName() + "/objects/" + name + ".iob: "
|
||||
+ w + "x" + h + "x" + d + ", " + object.getBlocks().size() + " block(s)" + tileNote);
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_SAVED_OBJECTS_IOB_X_X_BLOCK_S, MessageArgument.untrusted("value", engine.getData().getDataFolder().getName()), MessageArgument.untrusted("name", name), MessageArgument.untrusted("w", w), MessageArgument.untrusted("h", h), MessageArgument.untrusted("d", d), MessageArgument.untrusted("value2", object.getBlocks().size()), MessageArgument.untrusted("tileNote", tileNote)));
|
||||
LOGGER.info("Iris object save: {} {}x{}x{} blocks={} tilesSaved={} tilesSkipped={} -> {}", name, w, h, d, object.getBlocks().size(), tilesSaved[0], tilesSkipped[0], file.getAbsolutePath());
|
||||
return 1;
|
||||
}
|
||||
@@ -371,7 +374,7 @@ public final class ModdedObjectCommands {
|
||||
LOGGER.error("Iris object load failed for {}", key, e);
|
||||
}
|
||||
if (object == null || object.getBlocks().size() == 0) {
|
||||
IrisModdedCommands.fail(source, "Unknown or empty object: " + key);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_UNKNOWN_EMPTY_OBJECT, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -379,12 +382,12 @@ public final class ModdedObjectCommands {
|
||||
BlockPos target = at;
|
||||
if (target == null) {
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "Console must specify coordinates: /iris object paste at <x> <y> <z> [rotate <degrees>] " + key);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_CONSOLE_MUST_SPECIFY_COORDINATES_IRIS_OBJECT_PASTE_AT_X_Y, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
HitResult hit = player.pick(TARGET_RANGE, 1.0F, false);
|
||||
if (hit.getType() != HitResult.Type.BLOCK || !(hit instanceof BlockHitResult blockHit)) {
|
||||
IrisModdedCommands.fail(source, "You are not looking at a block within " + (int) TARGET_RANGE + " blocks.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_YOU_ARE_NOT_LOOKING_AT_BLOCK_WITHIN_BLOCKS, MessageArgument.untrusted("value", (int) TARGET_RANGE)));
|
||||
return 0;
|
||||
}
|
||||
target = blockHit.getBlockPos().above();
|
||||
@@ -398,14 +401,13 @@ public final class ModdedObjectCommands {
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris paste failed for {}", key, e);
|
||||
ModdedObjectUndo.record(player == null ? ModdedObjectUndo.CONSOLE : player.getUUID(), level, placer.undoSnapshot());
|
||||
IrisModdedCommands.fail(source, "Paste failed: " + e.getClass().getSimpleName() + " (partial changes recorded for undo)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_PASTE_FAILED_PARTIAL_CHANGES_RECORDED_UNDO, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
|
||||
return 0;
|
||||
}
|
||||
UUID owner = player == null ? ModdedObjectUndo.CONSOLE : player.getUUID();
|
||||
ModdedObjectUndo.record(owner, level, placer.undoSnapshot());
|
||||
String tileNote = tileNote(placer);
|
||||
IrisModdedCommands.ok(source, "Placed " + key + " at " + target.getX() + " " + target.getY() + " " + target.getZ()
|
||||
+ " rot=" + rotation + " (" + placer.writes() + " write(s), " + placer.nonAirWrites() + " non-air" + tileNote + ")");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_PLACED_AT_ROT_WRITE_S_NON_AIR, MessageArgument.untrusted("key", key), MessageArgument.untrusted("value", target.getX()), MessageArgument.untrusted("value2", target.getY()), MessageArgument.untrusted("value3", target.getZ()), MessageArgument.untrusted("rotation", rotation), MessageArgument.untrusted("value4", placer.writes()), MessageArgument.untrusted("value5", placer.nonAirWrites()), MessageArgument.untrusted("tileNote", tileNote)));
|
||||
LOGGER.info("Iris paste: {} at {},{},{} rot={} writes={} nonAir={} tilesRestored={} tilesSkipped={}",
|
||||
key, target.getX(), target.getY(), target.getZ(), rotation, placer.writes(), placer.nonAirWrites(), placer.restoredTiles(), placer.skippedTiles());
|
||||
return placer.writes() > 0 ? 1 : 0;
|
||||
@@ -414,16 +416,16 @@ public final class ModdedObjectCommands {
|
||||
private static int resize(CommandSourceStack source, int amount, ResizeOp op) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS));
|
||||
return 0;
|
||||
}
|
||||
if (!ModdedWandService.isHoldingWand(player)) {
|
||||
IrisModdedCommands.fail(source, "Hold your Iris wand. (/iris wand)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_HOLD_YOUR_IRIS_WAND_IRIS_WAND_2));
|
||||
return 0;
|
||||
}
|
||||
ModdedWandService.Selection selection = ModdedWandService.selection(player);
|
||||
if (selection == null) {
|
||||
IrisModdedCommands.fail(source, "No area selected.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_NO_AREA_SELECTED));
|
||||
return 0;
|
||||
}
|
||||
Direction direction = Direction.getApproximateNearest(player.getLookAngle());
|
||||
@@ -458,26 +460,25 @@ public final class ModdedObjectCommands {
|
||||
BlockPos first = new BlockPos(mins[0], mins[1], mins[2]);
|
||||
BlockPos second = new BlockPos(maxs[0], maxs[1], maxs[2]);
|
||||
ModdedWandService.setSelection(player, first, second);
|
||||
IrisModdedCommands.ok(source, op.name().toLowerCase(Locale.ROOT) + " " + amount + " " + direction.getName()
|
||||
+ ": " + describe(first, second));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_MESSAGE, MessageArgument.untrusted("value", op.name().toLowerCase(Locale.ROOT)), MessageArgument.untrusted("amount", amount), MessageArgument.untrusted("value2", direction.getName()), MessageArgument.untrusted("value3", describe(first, second))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int position(CommandSourceStack source, boolean first, boolean look) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_2));
|
||||
return 0;
|
||||
}
|
||||
if (!ModdedWandService.isHoldingWand(player)) {
|
||||
IrisModdedCommands.fail(source, "Ready your wand. (/iris wand)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_READY_YOUR_WAND_IRIS_WAND));
|
||||
return 0;
|
||||
}
|
||||
BlockPos pos;
|
||||
if (look) {
|
||||
HitResult hit = player.pick(TARGET_RANGE, 1.0F, false);
|
||||
if (hit.getType() != HitResult.Type.BLOCK || !(hit instanceof BlockHitResult blockHit)) {
|
||||
IrisModdedCommands.fail(source, "You are not looking at a block.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_YOU_ARE_NOT_LOOKING_AT_BLOCK));
|
||||
return 0;
|
||||
}
|
||||
pos = blockHit.getBlockPos();
|
||||
@@ -492,23 +493,23 @@ public final class ModdedObjectCommands {
|
||||
} else {
|
||||
ModdedWandService.setSelection(player, fallback, pos);
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Position " + (first ? 1 : 2) + " set to " + pos.getX() + " " + pos.getY() + " " + pos.getZ());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_POSITION_SET, MessageArgument.untrusted("value", (first ? 1 : 2)), MessageArgument.untrusted("value2", pos.getX()), MessageArgument.untrusted("value3", pos.getY()), MessageArgument.untrusted("value4", pos.getZ())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int autoSelect(CommandSourceStack source, boolean down) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_3));
|
||||
return 0;
|
||||
}
|
||||
if (!ModdedWandService.isHoldingWand(player)) {
|
||||
IrisModdedCommands.fail(source, "Hold your wand!");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_HOLD_YOUR_WAND));
|
||||
return 0;
|
||||
}
|
||||
ModdedWandService.Selection selection = ModdedWandService.selection(player);
|
||||
if (selection == null) {
|
||||
IrisModdedCommands.fail(source, "No area selected.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_NO_AREA_SELECTED_2));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = player.level();
|
||||
@@ -516,7 +517,7 @@ public final class ModdedObjectCommands {
|
||||
BlockPos max = selection.max();
|
||||
long volume = (long) (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1);
|
||||
if (volume > MAX_AUTOSELECT_VOLUME) {
|
||||
IrisModdedCommands.fail(source, "Selection too large for auto-select: " + volume + " blocks (max " + MAX_AUTOSELECT_VOLUME + ").");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_SELECTION_TOO_LARGE_AUTO_SELECT_BLOCKS_MAX, MessageArgument.untrusted("volume", volume), MessageArgument.untrusted("MAXAUTOSELECTVOLUME", MAX_AUTOSELECT_VOLUME)));
|
||||
return 0;
|
||||
}
|
||||
int levelMinY = level.getMinY();
|
||||
@@ -561,7 +562,7 @@ public final class ModdedObjectCommands {
|
||||
BlockPos first = new BlockPos(minX, bottomY, minZ);
|
||||
BlockPos second = new BlockPos(maxX, topMaxY, maxZ);
|
||||
ModdedWandService.setSelection(player, first, second);
|
||||
IrisModdedCommands.ok(source, "Auto-select complete: " + describe(first, second));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_AUTO_SELECT_COMPLETE, MessageArgument.untrusted("value", describe(first, second))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -590,11 +591,11 @@ public final class ModdedObjectCommands {
|
||||
LOGGER.error("Iris object load failed for {}", key, e);
|
||||
}
|
||||
if (object == null) {
|
||||
IrisModdedCommands.fail(source, "Unknown object: " + key);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_UNKNOWN_OBJECT, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Object Size: " + object.getW() + " * " + object.getH() + " * " + object.getD());
|
||||
IrisModdedCommands.ok(source, "Blocks Used: " + object.getBlocks().size());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_OBJECT_SIZE, MessageArgument.untrusted("value", object.getW()), MessageArgument.untrusted("value2", object.getH()), MessageArgument.untrusted("value3", object.getD())));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_BLOCKS_USED, MessageArgument.untrusted("value", object.getBlocks().size())));
|
||||
Map<String, Integer> counts = new HashMap<>();
|
||||
Iterator<PlatformBlockState> values = object.getBlocks().values();
|
||||
while (values.hasNext()) {
|
||||
@@ -603,15 +604,15 @@ public final class ModdedObjectCommands {
|
||||
}
|
||||
List<Map.Entry<String, Integer>> sorted = new ArrayList<>(counts.entrySet());
|
||||
sorted.sort(Comparator.comparingInt((Map.Entry<String, Integer> entry) -> entry.getValue()).reversed());
|
||||
IrisModdedCommands.ok(source, "== Blocks in object ==");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_BLOCKS_OBJECT));
|
||||
int shown = 0;
|
||||
for (Map.Entry<String, Integer> entry : sorted) {
|
||||
IrisModdedCommands.ok(source, " - " + entry.getKey() + " * " + entry.getValue());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_MESSAGE_2, MessageArgument.untrusted("value", entry.getKey()), MessageArgument.untrusted("value2", entry.getValue())));
|
||||
shown++;
|
||||
if (shown >= 10) {
|
||||
int remaining = sorted.size() - shown;
|
||||
if (remaining > 0) {
|
||||
IrisModdedCommands.ok(source, " + " + remaining + " other block state(s)");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_OTHER_BLOCK_STATE_S, MessageArgument.untrusted("remaining", remaining)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -630,22 +631,22 @@ public final class ModdedObjectCommands {
|
||||
LOGGER.error("Iris object load failed for {}", key, e);
|
||||
}
|
||||
if (object == null) {
|
||||
IrisModdedCommands.fail(source, "Unknown object: " + key);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_UNKNOWN_OBJECT_2, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Current Object Size: " + object.getW() + " * " + object.getH() + " * " + object.getD());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_CURRENT_OBJECT_SIZE, MessageArgument.untrusted("value", object.getW()), MessageArgument.untrusted("value2", object.getH()), MessageArgument.untrusted("value3", object.getD())));
|
||||
object.shrinkwrap();
|
||||
IrisModdedCommands.ok(source, "New Object Size: " + object.getW() + " * " + object.getH() + " * " + object.getD());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_NEW_OBJECT_SIZE, MessageArgument.untrusted("value", object.getW()), MessageArgument.untrusted("value2", object.getH()), MessageArgument.untrusted("value3", object.getD())));
|
||||
File file = object.getLoadFile();
|
||||
if (file == null) {
|
||||
IrisModdedCommands.fail(source, "Object has no load file; cannot persist the shrink.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_OBJECT_HAS_NO_LOAD_FILE_CANNOT_PERSIST_SHRINK));
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
object.write(file);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Iris object shrink save failed for {}", file.getAbsolutePath(), e);
|
||||
IrisModdedCommands.fail(source, "Failed to save object " + file.getName() + ": " + e.getMessage());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_FAILED_SAVE_OBJECT_2, MessageArgument.untrusted("value", file.getName()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage()))));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -667,7 +668,7 @@ public final class ModdedObjectCommands {
|
||||
try {
|
||||
reach = Integer.parseInt(lower.substring("reach=".length()));
|
||||
} catch (NumberFormatException e) {
|
||||
IrisModdedCommands.fail(source, "Invalid reach: " + token);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_INVALID_REACH, MessageArgument.untrusted("token", token)));
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
@@ -680,16 +681,20 @@ public final class ModdedObjectCommands {
|
||||
String target = targetBuilder.toString();
|
||||
List<TreePlausibilizeBatch.Target> targets = TreePlausibilizeBatch.resolve(target, data);
|
||||
if (targets.isEmpty()) {
|
||||
IrisModdedCommands.fail(source, "No objects matched: " + target);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_NO_OBJECTS_MATCHED, MessageArgument.untrusted("target", target)));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Plausibilize [reach=" + reach + (dryRun ? ", DRY" : "")
|
||||
+ "] queued " + targets.size() + " object(s)");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(
|
||||
ModdedCommandMessages.MODDED_OBJECT_COMMANDS_PLAUSIBILIZE_REACH_QUEUED_OBJECT_S,
|
||||
MessageArgument.trusted("reach", reach),
|
||||
MessageArgument.trusted("value", dryRun ? IrisLanguage.plain(RuntimeUiMessages.TREE_DRY_SUFFIX) : ""),
|
||||
MessageArgument.trusted("value2", targets.size())
|
||||
));
|
||||
boolean dry = dryRun;
|
||||
int reachFinal = reach;
|
||||
MinecraftServer server = source.getServer();
|
||||
J.a(() -> TreePlausibilizeBatch.run(targets, dry, reachFinal, data, (String line) ->
|
||||
server.execute(() -> IrisModdedCommands.ok(source, line))));
|
||||
J.a(() -> TreePlausibilizeBatch.run(targets, dry, reachFinal, data, (TreePlausibilizeBatch.Output output) ->
|
||||
server.execute(() -> IrisModdedCommands.ok(source, output.text()))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -698,11 +703,11 @@ public final class ModdedObjectCommands {
|
||||
UUID owner = player == null ? ModdedObjectUndo.CONSOLE : player.getUUID();
|
||||
int available = ModdedObjectUndo.size(owner);
|
||||
if (available == 0) {
|
||||
IrisModdedCommands.fail(source, "Nothing to undo.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_NOTHING_UNDO));
|
||||
return 0;
|
||||
}
|
||||
int reverted = ModdedObjectUndo.undo(owner, Math.min(amount, available));
|
||||
IrisModdedCommands.ok(source, "Reverted " + reverted + " paste(s)!");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_OBJECT_COMMANDS_REVERTED_PASTE_S, MessageArgument.untrusted("reverted", reverted)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+33
-37
@@ -39,6 +39,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class ModdedPackCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -101,7 +104,7 @@ public final class ModdedPackCommands {
|
||||
private static int validate(CommandSourceStack source, String pack) {
|
||||
File packsRoot = packsRoot();
|
||||
if (!packsRoot.isDirectory()) {
|
||||
IrisModdedCommands.fail(source, "Packs folder not found: " + packsRoot.getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_PACKS_FOLDER_NOT_FOUND, MessageArgument.untrusted("value", packsRoot.getAbsolutePath())));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -109,7 +112,7 @@ public final class ModdedPackCommands {
|
||||
if (pack == null || pack.isBlank()) {
|
||||
File[] dirs = packsRoot.listFiles(File::isDirectory);
|
||||
if (dirs == null || dirs.length == 0) {
|
||||
IrisModdedCommands.fail(source, "No packs to validate under " + packsRoot.getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_NO_PACKS_VALIDATE_UNDER, MessageArgument.untrusted("value", packsRoot.getAbsolutePath())));
|
||||
return 0;
|
||||
}
|
||||
for (File dir : dirs) {
|
||||
@@ -118,14 +121,14 @@ public final class ModdedPackCommands {
|
||||
} else {
|
||||
File target = PackDirectoryResolver.resolveExisting(packsRoot, pack);
|
||||
if (target == null) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' not found under " + packsRoot.getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_PACK_NOT_FOUND_UNDER, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("value", packsRoot.getAbsolutePath())));
|
||||
return 0;
|
||||
}
|
||||
targets.add(target);
|
||||
}
|
||||
|
||||
MinecraftServer server = source.getServer();
|
||||
IrisModdedCommands.ok(source, "Validating " + targets.size() + " pack(s)...");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_VALIDATING_PACK_S, MessageArgument.untrusted("value", targets.size())));
|
||||
Thread thread = new Thread(() -> {
|
||||
int broken = 0;
|
||||
for (File target : targets) {
|
||||
@@ -138,12 +141,12 @@ public final class ModdedPackCommands {
|
||||
server.execute(() -> report(source, result));
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris pack validation failed for {}", target.getName(), e);
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Validation of '" + target.getName() + "' failed: " + e.getMessage()));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_VALIDATION_FAILED, MessageArgument.untrusted("value", target.getName()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage())))));
|
||||
broken++;
|
||||
}
|
||||
}
|
||||
int brokenTotal = broken;
|
||||
server.execute(() -> IrisModdedCommands.ok(source, "Validation complete. Broken packs: " + brokenTotal + "/" + targets.size()));
|
||||
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_VALIDATION_COMPLETE_BROKEN_PACKS, MessageArgument.untrusted("brokenTotal", brokenTotal), MessageArgument.untrusted("value", targets.size()))));
|
||||
}, "Iris Pack Validator");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
@@ -153,7 +156,7 @@ public final class ModdedPackCommands {
|
||||
private static int cleanup(CommandSourceStack source, String pack, boolean apply) {
|
||||
File packFolder = PackDirectoryResolver.resolveExisting(packsRoot(), pack);
|
||||
if (packFolder == null) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' not found under " + packsRoot().getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_PACK_NOT_FOUND_UNDER_2, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("value", packsRoot().getAbsolutePath())));
|
||||
return 0;
|
||||
}
|
||||
MinecraftServer server = source.getServer();
|
||||
@@ -174,7 +177,7 @@ public final class ModdedPackCommands {
|
||||
private static int restore(CommandSourceStack source, String pack, boolean apply) {
|
||||
File packFolder = PackDirectoryResolver.resolveExisting(packsRoot(), pack);
|
||||
if (packFolder == null) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' not found under " + packsRoot().getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_PACK_NOT_FOUND_UNDER_3, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("value", packsRoot().getAbsolutePath())));
|
||||
return 0;
|
||||
}
|
||||
MinecraftServer server = source.getServer();
|
||||
@@ -196,21 +199,19 @@ public final class ModdedPackCommands {
|
||||
if (pack == null || pack.isBlank()) {
|
||||
Map<String, PackValidationResult> snapshot = PackValidationRegistry.snapshot();
|
||||
if (snapshot.isEmpty()) {
|
||||
IrisModdedCommands.fail(source, "No validation results recorded. Run /iris pack validate first.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_NO_VALIDATION_RESULTS_RECORDED_RUN_IRIS_PACK_VALIDATE_FIRST));
|
||||
return 0;
|
||||
}
|
||||
for (Map.Entry<String, PackValidationResult> entry : snapshot.entrySet()) {
|
||||
PackValidationResult result = entry.getValue();
|
||||
String tag = result.isLoadable() ? "OK" : "BROKEN";
|
||||
IrisModdedCommands.ok(source, tag + " " + entry.getKey()
|
||||
+ " (blocking=" + result.getBlockingErrors().size()
|
||||
+ ", warnings=" + result.getWarnings().size() + ")");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_BLOCKING_WARNINGS, MessageArgument.untrusted("tag", tag), MessageArgument.untrusted("value", entry.getKey()), MessageArgument.untrusted("value2", result.getBlockingErrors().size()), MessageArgument.untrusted("value3", result.getWarnings().size())));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
PackValidationResult result = PackValidationRegistry.get(pack);
|
||||
if (result == null) {
|
||||
IrisModdedCommands.fail(source, "No validation result for '" + pack + "'. Run /iris pack validate " + pack + ".");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_NO_VALIDATION_RESULT_RUN_IRIS_PACK_VALIDATE, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
return 0;
|
||||
}
|
||||
report(source, result);
|
||||
@@ -219,20 +220,19 @@ public final class ModdedPackCommands {
|
||||
|
||||
private static void report(CommandSourceStack source, PackValidationResult result) {
|
||||
if (result.isLoadable()) {
|
||||
IrisModdedCommands.ok(source, "Pack '" + result.getPackName() + "' is loadable."
|
||||
+ " (warnings=" + result.getWarnings().size() + ")");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_PACK_IS_LOADABLE_WARNINGS, MessageArgument.untrusted("value", result.getPackName()), MessageArgument.untrusted("value2", result.getWarnings().size())));
|
||||
} else {
|
||||
IrisModdedCommands.fail(source, "Pack '" + result.getPackName() + "' is BROKEN:");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_PACK_IS_BROKEN, MessageArgument.untrusted("value", result.getPackName())));
|
||||
for (String reason : result.getBlockingErrors()) {
|
||||
IrisModdedCommands.fail(source, " - " + reason);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_MESSAGE, MessageArgument.untrusted("reason", reason)));
|
||||
}
|
||||
}
|
||||
int warningMax = Math.min(10, result.getWarnings().size());
|
||||
for (int i = 0; i < warningMax; i++) {
|
||||
IrisModdedCommands.ok(source, " ! " + result.getWarnings().get(i));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_MESSAGE_2, MessageArgument.untrusted("value", result.getWarnings().get(i))));
|
||||
}
|
||||
if (result.getWarnings().size() > warningMax) {
|
||||
IrisModdedCommands.ok(source, " ... and " + (result.getWarnings().size() - warningMax) + " more warning(s).");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_MORE_WARNING_S, MessageArgument.untrusted("value", (result.getWarnings().size() - warningMax))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,13 +242,12 @@ public final class ModdedPackCommands {
|
||||
return;
|
||||
}
|
||||
if (!result.hasCandidates()) {
|
||||
IrisModdedCommands.ok(source, "No cleanup candidates found for pack '" + pack + "'.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_NO_CLEANUP_CANDIDATES_FOUND_PACK, MessageArgument.untrusted("pack", pack)));
|
||||
return;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Cleanup preview for pack '" + pack + "': "
|
||||
+ result.candidatePaths().size() + " candidate(s). No files were changed.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_CLEANUP_PREVIEW_PACK_CANDIDATE_S_NO_FILES_WERE_CHANGED, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("value", result.candidatePaths().size())));
|
||||
reportPaths(source, result.candidatePaths(), "candidate");
|
||||
IrisModdedCommands.ok(source, "Run /iris pack cleanup " + pack + " apply to quarantine after a fresh scan.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_RUN_IRIS_PACK_CLEANUP_APPLY_QUARANTINE_AFTER_FRESH_SCAN, MessageArgument.untrusted("pack", pack)));
|
||||
}
|
||||
|
||||
private static void reportCleanupApply(CommandSourceStack source, String pack, PackResourceCleanup.ApplyResult result) {
|
||||
@@ -258,11 +257,10 @@ public final class ModdedPackCommands {
|
||||
return;
|
||||
}
|
||||
if (!result.changed()) {
|
||||
IrisModdedCommands.ok(source, "No cleanup candidates found for pack '" + pack + "'.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_NO_CLEANUP_CANDIDATES_FOUND_PACK_2, MessageArgument.untrusted("pack", pack)));
|
||||
return;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Quarantined " + result.quarantinedPaths().size()
|
||||
+ " cleanup candidate(s) under " + result.quarantinePath() + ".");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_QUARANTINED_CLEANUP_CANDIDATE_S_UNDER, MessageArgument.untrusted("value", result.quarantinedPaths().size()), MessageArgument.untrusted("value2", result.quarantinePath())));
|
||||
reportPaths(source, result.quarantinedPaths(), "quarantined");
|
||||
}
|
||||
|
||||
@@ -272,23 +270,22 @@ public final class ModdedPackCommands {
|
||||
return;
|
||||
}
|
||||
if (!result.hasFiles()) {
|
||||
IrisModdedCommands.ok(source, "Nothing to restore for pack '" + pack + "'.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_NOTHING_RESTORE_PACK, MessageArgument.untrusted("pack", pack)));
|
||||
return;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Restore preview for " + result.dumpPath() + ": "
|
||||
+ result.filePaths().size() + " file(s). No files were changed.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_RESTORE_PREVIEW_FILE_S_NO_FILES_WERE_CHANGED, MessageArgument.untrusted("value", result.dumpPath()), MessageArgument.untrusted("value2", result.filePaths().size())));
|
||||
reportPaths(source, result.filePaths(), "file");
|
||||
if (!result.conflicts().isEmpty()) {
|
||||
IrisModdedCommands.fail(source, "Restore is blocked by " + result.conflicts().size() + " existing destination(s).");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_RESTORE_IS_BLOCKED_BY_EXISTING_DESTINATION_S, MessageArgument.untrusted("value", result.conflicts().size())));
|
||||
reportPaths(source, result.conflicts(), "conflict");
|
||||
return;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Run /iris pack restore " + pack + " apply to restore after a fresh conflict check.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_RUN_IRIS_PACK_RESTORE_APPLY_RESTORE_AFTER_FRESH_CONFLICT_CHECK, MessageArgument.untrusted("pack", pack)));
|
||||
}
|
||||
|
||||
private static void reportRestoreApply(CommandSourceStack source, String pack, PackResourceCleanup.RestoreResult result) {
|
||||
if (!result.conflicts().isEmpty()) {
|
||||
IrisModdedCommands.fail(source, "Restore refused because " + result.conflicts().size() + " destination(s) already exist.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_RESTORE_REFUSED_BECAUSE_DESTINATION_S_ALREADY_EXIST, MessageArgument.untrusted("value", result.conflicts().size())));
|
||||
reportPaths(source, result.conflicts(), "conflict");
|
||||
return;
|
||||
}
|
||||
@@ -297,21 +294,20 @@ public final class ModdedPackCommands {
|
||||
return;
|
||||
}
|
||||
if (!result.changed()) {
|
||||
IrisModdedCommands.ok(source, "Nothing to restore for pack '" + pack + "'.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_NOTHING_RESTORE_PACK_2, MessageArgument.untrusted("pack", pack)));
|
||||
return;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Restored " + result.restoredPaths().size()
|
||||
+ " file(s) from " + result.dumpPath() + ".");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_RESTORED_FILE_S_FROM, MessageArgument.untrusted("value", result.restoredPaths().size()), MessageArgument.untrusted("value2", result.dumpPath())));
|
||||
reportPaths(source, result.restoredPaths(), "restored");
|
||||
}
|
||||
|
||||
private static void reportPaths(CommandSourceStack source, List<String> paths, String label) {
|
||||
int max = Math.min(10, paths.size());
|
||||
for (int i = 0; i < max; i++) {
|
||||
IrisModdedCommands.ok(source, " - " + label + ": " + paths.get(i));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_MESSAGE_3, MessageArgument.untrusted("label", label), MessageArgument.untrusted("value", paths.get(i))));
|
||||
}
|
||||
if (paths.size() > max) {
|
||||
IrisModdedCommands.ok(source, " ... and " + (paths.size() - max) + " more.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_PACK_COMMANDS_MORE, MessageArgument.untrusted("value", (paths.size() - max))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+40
-16
@@ -1,13 +1,16 @@
|
||||
package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.iris.core.protocol.IrisProtocolServer;
|
||||
import art.arcane.iris.core.protocol.IrisSession;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.spi.protocol.IrisProtocol;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import art.arcane.volmlib.util.localization.TextKey;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerBossEvent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -35,7 +38,12 @@ public final class ModdedPregenBossBar {
|
||||
return;
|
||||
}
|
||||
viewer = player.getUUID();
|
||||
bar = new ServerBossEvent(BAR_ID, Component.literal("Iris Pregen starting..."), BossEvent.BossBarColor.GREEN, BossEvent.BossBarOverlay.PROGRESS);
|
||||
bar = new ServerBossEvent(
|
||||
BAR_ID,
|
||||
Component.literal(IrisLanguage.plain(RuntimeUiMessages.PREGEN_STARTING)),
|
||||
BossEvent.BossBarColor.GREEN,
|
||||
BossEvent.BossBarOverlay.PROGRESS
|
||||
);
|
||||
bar.setProgress(0.0F);
|
||||
bar.addPlayer(player);
|
||||
sinceUpdate = UPDATE_INTERVAL_TICKS;
|
||||
@@ -73,22 +81,38 @@ public final class ModdedPregenBossBar {
|
||||
}
|
||||
|
||||
private static Component nameFor(PregeneratorJob.PregenProgress progress) {
|
||||
MutableComponent name = Component.empty();
|
||||
name.append(ModdedCommandFeedback.text("Iris Pregen ", ModdedCommandFeedback.DARK_GREEN));
|
||||
name.append(ModdedCommandFeedback.text(Form.f(progress.generated()) + "/" + Form.f(progress.totalChunks()), ModdedCommandFeedback.VALUE));
|
||||
name.append(ModdedCommandFeedback.text(" " + String.format("%.1f", progress.percent()) + "%", ModdedCommandFeedback.USAGE));
|
||||
TextKey message = progress.paused()
|
||||
? RuntimeUiMessages.PREGEN_BOSSBAR_PAUSED
|
||||
: RuntimeUiMessages.PREGEN_BOSSBAR_RUNNING;
|
||||
if (progress.paused()) {
|
||||
name.append(ModdedCommandFeedback.text(" PAUSED", ModdedCommandFeedback.REQUIRED));
|
||||
return name;
|
||||
return ModdedCommandFeedback.text(IrisLanguage.plain(
|
||||
message,
|
||||
MessageArgument.trusted("generated", Form.f(progress.generated())),
|
||||
MessageArgument.trusted("total", Form.f(progress.totalChunks())),
|
||||
MessageArgument.trusted("percent", String.format("%.1f", progress.percent()))
|
||||
), ModdedCommandFeedback.DARK_GREEN);
|
||||
}
|
||||
name.append(ModdedCommandFeedback.text(" " + Form.f((int) progress.chunksPerSecond()) + "/s", ModdedCommandFeedback.VALUE));
|
||||
if (progress.eta() > 0L) {
|
||||
name.append(ModdedCommandFeedback.text(" ETA " + Form.duration(progress.eta(), 1), ModdedCommandFeedback.DARK_GREEN));
|
||||
}
|
||||
if (progress.failed() > 0L) {
|
||||
name.append(ModdedCommandFeedback.text(" failed " + Form.f(progress.failed()), ModdedCommandFeedback.REQUIRED));
|
||||
}
|
||||
return name;
|
||||
String eta = progress.eta() > 0L
|
||||
? IrisLanguage.plain(
|
||||
RuntimeUiMessages.PREGEN_ETA_FRAGMENT,
|
||||
MessageArgument.trusted("eta", Form.duration(progress.eta(), 1))
|
||||
)
|
||||
: "";
|
||||
String failed = progress.failed() > 0L
|
||||
? IrisLanguage.plain(
|
||||
RuntimeUiMessages.PREGEN_FAILED_FRAGMENT,
|
||||
MessageArgument.trusted("failed", Form.f(progress.failed()))
|
||||
)
|
||||
: "";
|
||||
return ModdedCommandFeedback.text(IrisLanguage.plain(
|
||||
message,
|
||||
MessageArgument.trusted("generated", Form.f(progress.generated())),
|
||||
MessageArgument.trusted("total", Form.f(progress.totalChunks())),
|
||||
MessageArgument.trusted("percent", String.format("%.1f", progress.percent())),
|
||||
MessageArgument.trusted("speed", Form.f((int) progress.chunksPerSecond())),
|
||||
MessageArgument.trusted("eta", eta),
|
||||
MessageArgument.trusted("failed", failed)
|
||||
), ModdedCommandFeedback.DARK_GREEN);
|
||||
}
|
||||
|
||||
private static boolean hasClientPregenHud(ServerPlayer player) {
|
||||
|
||||
+51
-23
@@ -19,6 +19,8 @@
|
||||
package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.iris.core.pregenerator.PregenPerformanceProfile;
|
||||
import art.arcane.iris.core.pregenerator.PregenTask;
|
||||
import art.arcane.iris.core.pregenerator.PregeneratorMethod;
|
||||
@@ -27,6 +29,7 @@ import art.arcane.iris.core.pregenerator.methods.CachedPregenMethod;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.volmlib.util.format.Form;
|
||||
import art.arcane.volmlib.util.math.Position2;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -119,41 +122,66 @@ public final class ModdedPregenJob {
|
||||
}
|
||||
|
||||
MutableComponent status = Component.empty();
|
||||
status.append(ModdedCommandFeedback.header("Iris Pregen"));
|
||||
status.append(ModdedCommandFeedback.header(IrisLanguage.plain(RuntimeUiMessages.PREGEN_HEADER)));
|
||||
status.append(Component.literal("\n"));
|
||||
status.append(ModdedCommandFeedback.text("Dimension ", ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(ModdedCommandFeedback.text(dimension, ModdedCommandFeedback.PARAMETER_ALT));
|
||||
status.append(ModdedCommandFeedback.text(" · Method ", ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(ModdedCommandFeedback.text(progress.method(), ModdedCommandFeedback.PARAMETER));
|
||||
status.append(ModdedCommandFeedback.text(IrisLanguage.plain(
|
||||
RuntimeUiMessages.PREGEN_STATUS_CONTEXT,
|
||||
MessageArgument.untrusted("dimension", dimension),
|
||||
MessageArgument.untrusted("method", progress.method())
|
||||
), ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(Component.literal("\n"));
|
||||
status.append(ModdedCommandFeedback.progressBar(progress.percent(), 32));
|
||||
status.append(ModdedCommandFeedback.text(" " + String.format("%.1f", progress.percent()) + "%", ModdedCommandFeedback.USAGE));
|
||||
status.append(ModdedCommandFeedback.text(" " + IrisLanguage.plain(
|
||||
RuntimeUiMessages.PREGEN_STATUS_PROGRESS,
|
||||
MessageArgument.trusted("percent", String.format("%.1f", progress.percent()))
|
||||
), ModdedCommandFeedback.USAGE));
|
||||
status.append(Component.literal("\n"));
|
||||
status.append(ModdedCommandFeedback.text("Chunks ", ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(ModdedCommandFeedback.text(Form.f(progress.generated()) + "/" + Form.f(progress.totalChunks()), ModdedCommandFeedback.VALUE));
|
||||
status.append(ModdedCommandFeedback.text(" · Speed ", ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(ModdedCommandFeedback.text(Form.f((int) progress.chunksPerSecond()) + "/s", ModdedCommandFeedback.VALUE));
|
||||
if (progress.failed() > 0) {
|
||||
status.append(ModdedCommandFeedback.text(" · Failed ", ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(ModdedCommandFeedback.text(Form.f(progress.failed()), ModdedCommandFeedback.REQUIRED));
|
||||
}
|
||||
status.append(ModdedCommandFeedback.text(chunksStatus(progress), ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(Component.literal("\n"));
|
||||
status.append(ModdedCommandFeedback.text("ETA ", ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(ModdedCommandFeedback.text(Form.duration(progress.eta(), 2), ModdedCommandFeedback.VALUE));
|
||||
status.append(ModdedCommandFeedback.text(" · Elapsed ", ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(ModdedCommandFeedback.text(Form.duration(progress.elapsed(), 2), ModdedCommandFeedback.VALUE));
|
||||
if (progress.paused()) {
|
||||
status.append(ModdedCommandFeedback.text(" · PAUSED", ModdedCommandFeedback.REQUIRED, true, false));
|
||||
}
|
||||
status.append(ModdedCommandFeedback.text(IrisLanguage.plain(
|
||||
progress.paused()
|
||||
? RuntimeUiMessages.PREGEN_STATUS_TIME_PAUSED
|
||||
: RuntimeUiMessages.PREGEN_STATUS_TIME,
|
||||
MessageArgument.trusted("eta", Form.duration(progress.eta(), 2)),
|
||||
MessageArgument.trusted("elapsed", Form.duration(progress.elapsed(), 2))
|
||||
), ModdedCommandFeedback.DARK_GREEN));
|
||||
status.append(Component.literal("\n"));
|
||||
status.append(ModdedCommandFeedback.button("Pause/Resume", "/iris pregen pause", "Toggle pregeneration pause state", true));
|
||||
status.append(ModdedCommandFeedback.button(
|
||||
IrisLanguage.plain(RuntimeUiMessages.PREGEN_PAUSE_BUTTON),
|
||||
"/iris pregen pause",
|
||||
IrisLanguage.plain(RuntimeUiMessages.PREGEN_PAUSE_HOVER),
|
||||
true
|
||||
));
|
||||
status.append(ModdedCommandFeedback.text(" ", ModdedCommandFeedback.OPTIONAL));
|
||||
status.append(ModdedCommandFeedback.button("Stop", "/iris pregen stop", "Finish the current region and stop pregeneration", true));
|
||||
status.append(ModdedCommandFeedback.button(
|
||||
IrisLanguage.plain(RuntimeUiMessages.PREGEN_STOP_BUTTON),
|
||||
"/iris pregen stop",
|
||||
IrisLanguage.plain(RuntimeUiMessages.PREGEN_STOP_HOVER),
|
||||
true
|
||||
));
|
||||
status.append(Component.literal("\n"));
|
||||
status.append(ModdedCommandFeedback.footer());
|
||||
return status;
|
||||
}
|
||||
|
||||
private static String chunksStatus(PregeneratorJob.PregenProgress progress) {
|
||||
if (progress.failed() > 0) {
|
||||
return IrisLanguage.plain(
|
||||
RuntimeUiMessages.PREGEN_STATUS_CHUNKS_FAILED,
|
||||
MessageArgument.trusted("generated", Form.f(progress.generated())),
|
||||
MessageArgument.trusted("total", Form.f(progress.totalChunks())),
|
||||
MessageArgument.trusted("speed", Form.f((int) progress.chunksPerSecond())),
|
||||
MessageArgument.trusted("failed", Form.f(progress.failed()))
|
||||
);
|
||||
}
|
||||
return IrisLanguage.plain(
|
||||
RuntimeUiMessages.PREGEN_STATUS_CHUNKS,
|
||||
MessageArgument.trusted("generated", Form.f(progress.generated())),
|
||||
MessageArgument.trusted("total", Form.f(progress.totalChunks())),
|
||||
MessageArgument.trusted("speed", Form.f((int) progress.chunksPerSecond()))
|
||||
);
|
||||
}
|
||||
|
||||
private static ActivePregen matchingActive(String worldIdentity) {
|
||||
ActivePregen active = ACTIVE.get();
|
||||
return active != null && active.targets(worldIdentity) ? active : null;
|
||||
|
||||
+3
-1
@@ -61,6 +61,8 @@ import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
public final class ModdedRegen {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final int APPLY_AHEAD = 8;
|
||||
@@ -88,7 +90,7 @@ public final class ModdedRegen {
|
||||
|
||||
public static void start(CommandSourceStack source, ServerLevel level, IrisModdedChunkGenerator generator, Engine engine, ServerPlayer player, int radius) {
|
||||
if (!ACTIVE.compareAndSet(false, true)) {
|
||||
IrisModdedCommands.fail(source, "A regen is already running.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_REGEN_REGEN_IS_ALREADY_RUNNING));
|
||||
return;
|
||||
}
|
||||
int centerX = player.blockPosition().getX() >> 4;
|
||||
|
||||
+13
-11
@@ -48,6 +48,9 @@ import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class ModdedStructureCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -116,7 +119,7 @@ public final class ModdedStructureCommands {
|
||||
private static IrisData dataFor(CommandSourceStack source) {
|
||||
Engine engine = IrisModdedCommands.engineFor(source.getLevel());
|
||||
if (engine == null) {
|
||||
IrisModdedCommands.fail(source, "This dimension is not generated by Iris. Run this from an Iris dimension so the pack can be resolved.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_RUN_THIS_FROM));
|
||||
return null;
|
||||
}
|
||||
return engine.getData();
|
||||
@@ -128,7 +131,7 @@ public final class ModdedStructureCommands {
|
||||
return 0;
|
||||
}
|
||||
File file = StructureIndexService.write(data);
|
||||
IrisModdedCommands.ok(source, "Wrote structure index: " + file.getPath());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_WROTE_STRUCTURE_INDEX, MessageArgument.untrusted("value", file.getPath())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -140,14 +143,14 @@ public final class ModdedStructureCommands {
|
||||
String key = keyRaw.trim();
|
||||
IrisStructure structure = data.load(IrisStructure.class, key, false);
|
||||
if (structure == null) {
|
||||
IrisModdedCommands.fail(source, "No iris structure '" + key + "' in this pack");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_NO_IRIS_STRUCTURE_THIS_PACK, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
StructureAssembler assembler = StructureAssembler.forData(
|
||||
data, structure, new IrisPosition(0, 64, 0));
|
||||
KList<PlacedStructurePiece> pieces = assembler.assemble(new RNG(1234));
|
||||
if (pieces == null || pieces.isEmpty()) {
|
||||
IrisModdedCommands.fail(source, "Structure '" + key + "' assembled 0 pieces (check startPool '" + structure.getStartPool() + "')");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_STRUCTURE_ASSEMBLED_0_PIECES_CHECK_STARTPOOL, MessageArgument.untrusted("key", key), MessageArgument.untrusted("value", structure.getStartPool())));
|
||||
return 0;
|
||||
}
|
||||
int minX = Integer.MAX_VALUE;
|
||||
@@ -160,15 +163,14 @@ public final class ModdedStructureCommands {
|
||||
maxX = Math.max(maxX, piece.getMaxX());
|
||||
maxZ = Math.max(maxZ, piece.getMaxZ());
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Structure '" + key + "': " + pieces.size() + " pieces, footprint "
|
||||
+ (maxX - minX + 1) + "x" + (maxZ - minZ + 1) + " blocks (sample seed 1234)");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_STRUCTURE_PIECES_FOOTPRINT_X_BLOCKS_SAMPLE_SEED_1234, MessageArgument.untrusted("key", key), MessageArgument.untrusted("value", pieces.size()), MessageArgument.untrusted("value2", (maxX - minX + 1)), MessageArgument.untrusted("value3", (maxZ - minZ + 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int place(CommandSourceStack source, String keyRaw) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players (the structure is assembled at your position).");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_STRUCTURE_IS));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel level = source.getLevel();
|
||||
@@ -180,7 +182,7 @@ public final class ModdedStructureCommands {
|
||||
String key = keyRaw.trim();
|
||||
IrisStructure structure = data.load(IrisStructure.class, key, false);
|
||||
if (structure == null) {
|
||||
IrisModdedCommands.fail(source, "No iris structure '" + key + "' in this pack");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_NO_IRIS_STRUCTURE_THIS_PACK_2, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
int originX = player.blockPosition().getX();
|
||||
@@ -191,7 +193,7 @@ public final class ModdedStructureCommands {
|
||||
RNG rng = new RNG((long) originX * 341873128712L + originZ);
|
||||
KList<PlacedStructurePiece> pieces = assembler.assemble(rng);
|
||||
if (pieces == null || pieces.isEmpty()) {
|
||||
IrisModdedCommands.fail(source, "Structure '" + key + "' assembled 0 pieces");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_STRUCTURE_ASSEMBLED_0_PIECES, MessageArgument.untrusted("key", key)));
|
||||
return 0;
|
||||
}
|
||||
ModdedObjectPlacer placer = new ModdedObjectPlacer(level, engine);
|
||||
@@ -210,12 +212,12 @@ public final class ModdedStructureCommands {
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris structure place failed for {}", key, e);
|
||||
ModdedObjectUndo.record(owner, level, placer.undoSnapshot());
|
||||
IrisModdedCommands.fail(source, "Place failed: " + e.getClass().getSimpleName() + " (partial changes recorded for undo)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_PLACE_FAILED_PARTIAL_CHANGES_RECORDED_UNDO, MessageArgument.untrusted("value", e.getClass().getSimpleName())));
|
||||
return 0;
|
||||
}
|
||||
ModdedObjectUndo.record(owner, level, placer.undoSnapshot());
|
||||
String tileNote = ModdedObjectCommands.tileNote(placer);
|
||||
IrisModdedCommands.ok(source, "Placed '" + key + "' (" + pieces.size() + " pieces, " + placer.writes() + " write(s)" + tileNote + ") at your location. /iris object undo to revert.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STRUCTURE_COMMANDS_PLACED_PIECES_WRITE_S_AT_YOUR_LOCATION_IRIS_OBJECT_UNDO, MessageArgument.untrusted("key", key), MessageArgument.untrusted("value", pieces.size()), MessageArgument.untrusted("value2", placer.writes()), MessageArgument.untrusted("tileNote", tileNote)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+57
-54
@@ -82,6 +82,9 @@ import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class ModdedStudioCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -184,7 +187,7 @@ public final class ModdedStudioCommands {
|
||||
}
|
||||
|
||||
private static int openHelp(CommandSourceStack source) {
|
||||
IrisModdedCommands.fail(source, "Provide a dimension pack: /iris studio open <pack> [seed]");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PROVIDE_DIMENSION_PACK_IRIS_STUDIO_OPEN_PACK_SEED));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -215,22 +218,22 @@ public final class ModdedStudioCommands {
|
||||
}
|
||||
if (generatorKey == null || generatorKey.isBlank()) {
|
||||
NoiseExplorerGUI.launch();
|
||||
IrisModdedCommands.ok(source, "Opening the Noise Explorer on the server display.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_OPENING_NOISE_EXPLORER_ON_SERVER_DISPLAY));
|
||||
return 1;
|
||||
}
|
||||
if (engine == null) {
|
||||
IrisModdedCommands.fail(source, "This dimension is not generated by Iris; run /iris studio noise from an Iris dimension to resolve generators, or omit the generator name.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_RUN_IRIS_STUDIO));
|
||||
return 0;
|
||||
}
|
||||
IrisGenerator generator = engine.getData().getGeneratorLoader().load(generatorKey.trim());
|
||||
if (generator == null) {
|
||||
IrisModdedCommands.fail(source, "Unknown generator '" + generatorKey + "' in pack " + engine.getDimension().getLoadKey() + ".");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_UNKNOWN_GENERATOR_PACK, MessageArgument.untrusted("generatorKey", generatorKey), MessageArgument.untrusted("value", engine.getDimension().getLoadKey())));
|
||||
return 0;
|
||||
}
|
||||
long mixedSeed = new RNG(seed).nextParallelRNG(3245).lmax();
|
||||
Supplier<Function2<Double, Double, Double>> supplier = () -> (Double x, Double z) -> generator.getHeight(x, z, mixedSeed);
|
||||
NoiseExplorerGUI.launch(supplier, generatorKey.trim());
|
||||
IrisModdedCommands.ok(source, "Opening the Noise Explorer for generator '" + generatorKey.trim() + "' (seed " + seed + ").");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_OPENING_NOISE_EXPLORER_GENERATOR_SEED, MessageArgument.untrusted("value", generatorKey.trim()), MessageArgument.untrusted("seed", seed)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -238,7 +241,7 @@ public final class ModdedStudioCommands {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = IrisModdedCommands.engineFor(level);
|
||||
if (engine == null) {
|
||||
IrisModdedCommands.fail(source, "This dimension is not generated by Iris; stand in an Iris (or studio) dimension and run /iris studio map.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_STAND_IRIS_STUDIO));
|
||||
return 0;
|
||||
}
|
||||
if (!GuiHost.isAvailable() || !IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||
@@ -248,7 +251,7 @@ public final class ModdedStudioCommands {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
ModdedGuiHost.bindContext(source.getServer(), level, engine, player == null ? null : player.getUUID());
|
||||
VisionGUI.launch(engine);
|
||||
IrisModdedCommands.ok(source, "Opening the Vision map for " + level.dimension().identifier() + " on the server display.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_OPENING_VISION_MAP_ON_SERVER_DISPLAY, MessageArgument.untrusted("value", level.dimension().identifier())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -269,10 +272,10 @@ public final class ModdedStudioCommands {
|
||||
workspace = ModdedWorkspaceGenerator.writeWorkspace(IrisData.get(folder), folder);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Iris workspace write failed for {}", folder, e);
|
||||
IrisModdedCommands.fail(source, "Failed to write workspace for " + folder.getAbsolutePath() + ": " + e.getMessage());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_FAILED_WRITE_WORKSPACE, MessageArgument.untrusted("value", folder.getAbsolutePath()), MessageArgument.untrusted("value2", String.valueOf(e.getMessage()))));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Workspace regenerated: " + workspace.getAbsolutePath() + " with JSON schemas for autocomplete.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_WORKSPACE_REGENERATED_WITH_JSON_SCHEMAS_AUTOCOMPLETE, MessageArgument.untrusted("value", workspace.getAbsolutePath())));
|
||||
if (!open) {
|
||||
return 1;
|
||||
}
|
||||
@@ -284,10 +287,10 @@ public final class ModdedStudioCommands {
|
||||
Desktop.getDesktop().open(workspace);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris workspace open failed for {}", workspace, e);
|
||||
IrisModdedCommands.fail(source, "Could not open " + workspace.getName() + ": " + e.getClass().getSimpleName());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_COULD_NOT_OPEN, MessageArgument.untrusted("value", workspace.getName()), MessageArgument.untrusted("value2", e.getClass().getSimpleName())));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Opening " + workspace.getName() + " in your editor.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_OPENING_YOUR_EDITOR, MessageArgument.untrusted("value", workspace.getName())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -319,14 +322,14 @@ public final class ModdedStudioCommands {
|
||||
if (name == null || name.isBlank()) {
|
||||
Engine engine = IrisModdedCommands.engineFor(source.getLevel());
|
||||
if (engine == null || engine.getDimension() == null) {
|
||||
IrisModdedCommands.fail(source, "This dimension is not generated by Iris; specify a pack name explicitly.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS_SPECIFY_PACK_NAME));
|
||||
return null;
|
||||
}
|
||||
name = engine.getDimension().getLoadKey();
|
||||
}
|
||||
File folder = new File(ModdedPackCommands.packsRoot(), name);
|
||||
if (!folder.isDirectory() || !new File(folder, "dimensions").isDirectory()) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + name + "' not found under " + ModdedPackCommands.packsRoot().getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_NOT_FOUND_UNDER, MessageArgument.untrusted("name", name), MessageArgument.untrusted("value", ModdedPackCommands.packsRoot().getAbsolutePath())));
|
||||
return null;
|
||||
}
|
||||
return folder;
|
||||
@@ -346,14 +349,14 @@ public final class ModdedStudioCommands {
|
||||
|
||||
private static int open(CommandSourceStack source, String pack, long seed) {
|
||||
if (pack == null || pack.isBlank()) {
|
||||
IrisModdedCommands.fail(source, "Provide a dimension pack: /iris studio open <pack> [seed]");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PROVIDE_DIMENSION_PACK_IRIS_STUDIO_OPEN_PACK_SEED_2));
|
||||
return 0;
|
||||
}
|
||||
ServerPlayer player = source.getPlayer();
|
||||
UUID owner = player == null ? CONSOLE_OWNER : player.getUUID();
|
||||
String dimensionId = player == null ? studioConsoleDimensionId() : studioDimensionId(player);
|
||||
MinecraftServer server = source.getServer();
|
||||
IrisModdedCommands.ok(source, "Opening studio for '" + pack + "' (seed " + seed + ")...");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_OPENING_STUDIO_SEED, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("seed", seed)));
|
||||
Thread thread = new Thread(() -> openAsync(source, server, owner, dimensionId, pack, seed), "Iris Studio Open");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
@@ -364,18 +367,18 @@ public final class ModdedStudioCommands {
|
||||
try {
|
||||
File packFolder = new File(ModdedPackCommands.packsRoot(), pack);
|
||||
if (!new File(packFolder, "dimensions/" + pack + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.ok(source, "Pack '" + pack + "' missing; downloading IrisDimensions/" + pack + "..."));
|
||||
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_MISSING_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack))));
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), pack, "master",
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
if (!installed || !new File(packFolder, "dimensions/" + pack + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Pack '" + pack + "' could not be downloaded; check the name and try /iris download " + pack + "."));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_COULD_NOT_BE_DOWNLOADED_CHECK_NAME_TRY_IRIS_DOWNLOAD, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
IrisData data = IrisData.get(packFolder);
|
||||
IrisDimension dimension = data.getDimensionLoader().load(pack);
|
||||
if (dimension == null) {
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Pack '" + pack + "' has no dimensions/" + pack + ".json"));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_HAS_NO_DIMENSIONS_JSON, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack))));
|
||||
return;
|
||||
}
|
||||
server.execute(() -> {
|
||||
@@ -387,7 +390,7 @@ public final class ModdedStudioCommands {
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris studio open failed for {}", pack, e);
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Studio open failed: " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage())));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_OPEN_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e)))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +400,7 @@ public final class ModdedStudioCommands {
|
||||
handle = ModdedDimensionManager.create(server, dimensionId, pack, pack, seed);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris console studio injection failed for {} ({})", dimensionId, pack, e);
|
||||
IrisModdedCommands.fail(source, "Studio injection failed: " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage()));
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_INJECTION_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
|
||||
return;
|
||||
}
|
||||
STUDIOS.put(CONSOLE_OWNER, dimensionId);
|
||||
@@ -411,10 +414,10 @@ public final class ModdedStudioCommands {
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris console studio surface probe failed for {}", dimensionId, e);
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Console studio open: " + dimensionId + " now runs '" + pack + "' seed " + seed + " (transient; not written to iris-dimensions.json and cleared on restart).");
|
||||
IrisModdedCommands.ok(source, "Enter it with: /execute in " + dimensionId + " run tp @s 8.5 " + surface + " 8.5");
|
||||
IrisModdedCommands.ok(source, "Pregen it with: /iris pregen start <radius> " + dimensionId);
|
||||
IrisModdedCommands.ok(source, "Remove it with: /iris studio close");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_CONSOLE_STUDIO_OPEN_NOW_RUNS_SEED_TRANSIENT_NOT_WRITTEN_IRIS, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("seed", seed)));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_ENTER_IT_WITH_EXECUTE_RUN_TP_S_8_5_8, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("surface", surface)));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PREGEN_IT_WITH_IRIS_PREGEN_START_RADIUS, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_REMOVE_IT_WITH_IRIS_STUDIO_CLOSE));
|
||||
}
|
||||
|
||||
private static void injectAndTeleport(CommandSourceStack source, MinecraftServer server, UUID owner, String dimensionId, String pack, long seed) {
|
||||
@@ -427,7 +430,7 @@ public final class ModdedStudioCommands {
|
||||
handle = ModdedDimensionManager.create(server, dimensionId, pack, pack, seed);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris studio injection failed for {} ({})", dimensionId, pack, e);
|
||||
IrisModdedCommands.fail(source, "Studio injection failed: " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage()));
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_INJECTION_FAILED_2, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
|
||||
return;
|
||||
}
|
||||
STUDIOS.put(owner, dimensionId);
|
||||
@@ -442,7 +445,7 @@ public final class ModdedStudioCommands {
|
||||
LOGGER.error("Iris studio surface probe failed for {}", dimensionId, e);
|
||||
}
|
||||
player.teleportTo(studio, 8.5D, surface, 8.5D, java.util.Set.<Relative>of(), player.getYRot(), player.getXRot(), false);
|
||||
IrisModdedCommands.ok(source, "Studio open: " + dimensionId + " now runs '" + pack + "' seed " + seed + ". Use /iris studio close when done.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_OPEN_NOW_RUNS_SEED_USE_IRIS_STUDIO_CLOSE_WHEN, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("seed", seed)));
|
||||
}
|
||||
|
||||
private static int close(CommandSourceStack source) {
|
||||
@@ -451,17 +454,17 @@ public final class ModdedStudioCommands {
|
||||
UUID owner = player == null ? CONSOLE_OWNER : player.getUUID();
|
||||
String dimensionId = STUDIOS.remove(owner);
|
||||
if (dimensionId == null) {
|
||||
IrisModdedCommands.fail(source, "You do not have an open studio. Use /iris studio open <pack> first.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_YOU_DO_NOT_HAVE_OPEN_STUDIO_USE_IRIS_STUDIO_OPEN));
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
ModdedDimensionManager.remove(server, dimensionId, true);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris studio close failed for {}", dimensionId, e);
|
||||
IrisModdedCommands.fail(source, "Studio close failed: " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage()));
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_CLOSE_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Studio closed: " + dimensionId + " was evacuated, unloaded and its region data deleted.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_STUDIO_CLOSED_WAS_EVACUATED_UNLOADED_ITS_REGION_DATA_DELETED, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -475,14 +478,14 @@ public final class ModdedStudioCommands {
|
||||
}
|
||||
}
|
||||
if (studios.isEmpty()) {
|
||||
IrisModdedCommands.ok(source, "No studio dimensions are currently open.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_NO_STUDIO_DIMENSIONS_ARE_CURRENTLY_OPEN));
|
||||
return 1;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Active studio dimension(s): " + studios.size());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_ACTIVE_STUDIO_DIMENSION_S, MessageArgument.untrusted("value", studios.size())));
|
||||
for (ModdedDimensionManager.Handle handle : studios) {
|
||||
UUID owner = ownerOf(handle.dimensionId());
|
||||
String ownerName = owner == null ? "unclaimed" : ownerName(server, owner);
|
||||
IrisModdedCommands.ok(source, " " + handle.dimensionId() + ": pack '" + handle.pack() + "' seed " + handle.seed() + " owner " + ownerName);
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_SEED_OWNER, MessageArgument.untrusted("value", handle.dimensionId()), MessageArgument.untrusted("value2", handle.pack()), MessageArgument.untrusted("value3", handle.seed()), MessageArgument.untrusted("ownerName", ownerName)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -507,19 +510,19 @@ public final class ModdedStudioCommands {
|
||||
private static int tpStudio(CommandSourceStack source) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS));
|
||||
return 0;
|
||||
}
|
||||
MinecraftServer server = source.getServer();
|
||||
String dimensionId = STUDIOS.get(player.getUUID());
|
||||
if (dimensionId == null) {
|
||||
IrisModdedCommands.fail(source, "You do not have an open studio. Use /iris studio open <pack> first.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_YOU_DO_NOT_HAVE_OPEN_STUDIO_USE_IRIS_STUDIO_OPEN_2));
|
||||
return 0;
|
||||
}
|
||||
ServerLevel studio = ModdedDimensionManager.level(server, dimensionId);
|
||||
if (studio == null) {
|
||||
STUDIOS.remove(player.getUUID());
|
||||
IrisModdedCommands.fail(source, "Your studio dimension is no longer loaded. Use /iris studio open <pack> again.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_YOUR_STUDIO_DIMENSION_IS_NO_LONGER_LOADED_USE_IRIS_STUDIO));
|
||||
return 0;
|
||||
}
|
||||
int surface = studio.getMaxY();
|
||||
@@ -532,7 +535,7 @@ public final class ModdedStudioCommands {
|
||||
LOGGER.error("Iris tpstudio surface probe failed", e);
|
||||
}
|
||||
player.teleportTo(studio, 8.5D, surface, 8.5D, java.util.Set.<Relative>of(), player.getYRot(), player.getXRot(), false);
|
||||
IrisModdedCommands.ok(source, "Teleported to your studio (" + dimensionId + ").");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_TELEPORTED_YOUR_STUDIO, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -544,36 +547,36 @@ public final class ModdedStudioCommands {
|
||||
IrisData data = IrisData.get(folder);
|
||||
IrisDimension dimension = data.getDimensionLoader().load(folder.getName());
|
||||
if (dimension == null) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + folder.getName() + "' has no dimensions/" + folder.getName() + ".json");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_HAS_NO_DIMENSIONS_JSON_2, MessageArgument.untrusted("value", folder.getName()), MessageArgument.untrusted("value2", folder.getName())));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_HAS_VERSION, MessageArgument.untrusted("value", dimension.getName()), MessageArgument.untrusted("value2", dimension.getVersion())));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int create(CommandSourceStack source, String nameRaw, String template) {
|
||||
String name = nameRaw.toLowerCase(Locale.ROOT);
|
||||
if (!PROJECT_NAME.matcher(name).matches()) {
|
||||
IrisModdedCommands.fail(source, "Invalid project name '" + nameRaw + "' (allowed: a-z, 0-9, _ and -)");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_INVALID_PROJECT_NAME_ALLOWED_Z_0_9, MessageArgument.untrusted("nameRaw", nameRaw)));
|
||||
return 0;
|
||||
}
|
||||
File packsRoot = ModdedPackCommands.packsRoot();
|
||||
File target = new File(packsRoot, name);
|
||||
if (target.exists()) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + name + "' already exists at " + target.getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_ALREADY_EXISTS_AT, MessageArgument.untrusted("name", name), MessageArgument.untrusted("value", target.getAbsolutePath())));
|
||||
return 0;
|
||||
}
|
||||
MinecraftServer server = source.getServer();
|
||||
IrisModdedCommands.ok(source, "Creating project '" + name + "' from template '" + template + "'...");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_CREATING_PROJECT_FROM_TEMPLATE, MessageArgument.untrusted("name", name), MessageArgument.untrusted("template", template)));
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
File templateFolder = new File(packsRoot, template);
|
||||
if (!new File(templateFolder, "dimensions/" + template + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.ok(source, "Template '" + template + "' is not installed; downloading IrisDimensions/" + template + "..."));
|
||||
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_TEMPLATE_IS_NOT_INSTALLED_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("template", template), MessageArgument.untrusted("template2", template))));
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), template, "master",
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
if (!installed || !new File(templateFolder, "dimensions/" + template + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Template '" + template + "' could not be downloaded; install a pack with dimensions/" + template + ".json first."));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_TEMPLATE_COULD_NOT_BE_DOWNLOADED_INSTALL_PACK_WITH_DIMENSIONS_JSON, MessageArgument.untrusted("template", template), MessageArgument.untrusted("template2", template))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -584,12 +587,12 @@ public final class ModdedStudioCommands {
|
||||
LOGGER.error("Iris studio create workspace generation failed for {}", name, e);
|
||||
}
|
||||
server.execute(() -> {
|
||||
IrisModdedCommands.ok(source, "Created project '" + name + "' at " + target.getAbsolutePath());
|
||||
IrisModdedCommands.ok(source, "Edit dimensions/" + name + ".json and the rest of the pack. A VSCode workspace with JSON schema autocomplete was generated; open it or rerun /iris studio vscode.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_CREATED_PROJECT_AT, MessageArgument.untrusted("name", name), MessageArgument.untrusted("value", target.getAbsolutePath())));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_EDIT_DIMENSIONS_JSON_REST_PACK_VSCODE_WORKSPACE_WITH_JSON_SCHEMA, MessageArgument.untrusted("name", name)));
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris studio create failed for {}", name, e);
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Project creation failed: " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage())));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PROJECT_CREATION_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e)))));
|
||||
}
|
||||
}, "Iris Studio Create");
|
||||
thread.setDaemon(true);
|
||||
@@ -604,14 +607,14 @@ public final class ModdedStudioCommands {
|
||||
}
|
||||
MinecraftServer server = source.getServer();
|
||||
String dimKey = folder.getName();
|
||||
IrisModdedCommands.ok(source, "Packaging dimension '" + dimKey + "'...");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACKAGING_DIMENSION, MessageArgument.untrusted("dimKey", dimKey)));
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
File result = compilePackage(folder, dimKey);
|
||||
server.execute(() -> IrisModdedCommands.ok(source, "Package compiled: " + result.getAbsolutePath()));
|
||||
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACKAGE_COMPILED, MessageArgument.untrusted("value", result.getAbsolutePath()))));
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris package failed for {}", dimKey, e);
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Packaging failed: " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage())));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACKAGING_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e)))));
|
||||
}
|
||||
}, "Iris Studio Package");
|
||||
thread.setDaemon(true);
|
||||
@@ -758,18 +761,18 @@ public final class ModdedStudioCommands {
|
||||
private static int regions(CommandSourceStack source, int radius) {
|
||||
ServerPlayer player = source.getPlayer();
|
||||
if (player == null) {
|
||||
IrisModdedCommands.fail(source, "This command can only be used by players (sampling is centered on your position).");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_THIS_COMMAND_CAN_ONLY_BE_USED_BY_PLAYERS_SAMPLING_IS));
|
||||
return 0;
|
||||
}
|
||||
Engine engine = IrisModdedCommands.engineFor(source.getLevel());
|
||||
if (engine == null) {
|
||||
IrisModdedCommands.fail(source, "This dimension is not generated by Iris.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_THIS_DIMENSION_IS_NOT_GENERATED_BY_IRIS));
|
||||
return 0;
|
||||
}
|
||||
MinecraftServer server = source.getServer();
|
||||
int blockX = player.blockPosition().getX();
|
||||
int blockZ = player.blockPosition().getZ();
|
||||
IrisModdedCommands.ok(source, "Sampling region distribution in " + (radius * 2) + "x" + (radius * 2) + " chunks around you...");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_SAMPLING_REGION_DISTRIBUTION_X_CHUNKS_AROUND_YOU, MessageArgument.untrusted("value", (radius * 2)), MessageArgument.untrusted("value2", (radius * 2))));
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
int diameter = radius * 2;
|
||||
@@ -787,11 +790,11 @@ public final class ModdedStudioCommands {
|
||||
server.execute(() -> counts.forEach((String key, AtomicInteger count) -> {
|
||||
IrisRegion region = engine.getData().getRegionLoader().load(key);
|
||||
String rarity = region == null ? "?" : String.valueOf(region.getRarity());
|
||||
IrisModdedCommands.ok(source, key + ": rarity=" + rarity + " / " + Form.f((double) count.get() / totalTasks * 100, 2) + "%");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_RARITY, MessageArgument.untrusted("key", key), MessageArgument.untrusted("rarity", rarity), MessageArgument.untrusted("value", Form.f((double) count.get() / totalTasks * 100, 2))));
|
||||
}));
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris region sampling failed", e);
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Region sampling failed: " + e.getClass().getSimpleName()));
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_REGION_SAMPLING_FAILED, MessageArgument.untrusted("value", e.getClass().getSimpleName()))));
|
||||
}
|
||||
}, "Iris Region Sampler");
|
||||
thread.setDaemon(true);
|
||||
|
||||
+15
-6
@@ -18,6 +18,9 @@
|
||||
|
||||
package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
@@ -78,10 +81,10 @@ public final class ModdedWandService {
|
||||
|
||||
public static ItemStack createWand() {
|
||||
ItemStack stack = new ItemStack(Items.BLAZE_ROD);
|
||||
stack.set(DataComponents.CUSTOM_NAME, Component.literal("Wand of Iris").withStyle(ChatFormatting.BOLD, ChatFormatting.GOLD));
|
||||
stack.set(DataComponents.CUSTOM_NAME, Component.literal(IrisLanguage.plain(RuntimeUiMessages.WAND_NAME)).withStyle(ChatFormatting.BOLD, ChatFormatting.GOLD));
|
||||
stack.set(DataComponents.LORE, new ItemLore(List.of(
|
||||
Component.literal("Left click a block to set the first corner"),
|
||||
Component.literal("Right click a block to set the second corner"))));
|
||||
Component.literal(IrisLanguage.plain(RuntimeUiMessages.WAND_LORE_FIRST)),
|
||||
Component.literal(IrisLanguage.plain(RuntimeUiMessages.WAND_LORE_SECOND)))));
|
||||
stack.set(DataComponents.UNBREAKABLE, Unit.INSTANCE);
|
||||
stack.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, Boolean.TRUE);
|
||||
stack.set(DataComponents.CUSTOM_DATA, CustomData.of(flagTag(WAND_TAG)));
|
||||
@@ -90,9 +93,9 @@ public final class ModdedWandService {
|
||||
|
||||
public static ItemStack createDust() {
|
||||
ItemStack stack = new ItemStack(Items.GLOWSTONE_DUST);
|
||||
stack.set(DataComponents.CUSTOM_NAME, Component.literal("Dust of Revealing").withStyle(ChatFormatting.BOLD, ChatFormatting.YELLOW));
|
||||
stack.set(DataComponents.CUSTOM_NAME, Component.literal(IrisLanguage.plain(RuntimeUiMessages.DUST_NAME)).withStyle(ChatFormatting.BOLD, ChatFormatting.YELLOW));
|
||||
stack.set(DataComponents.LORE, new ItemLore(List.of(
|
||||
Component.literal("Right click on a block to reveal it's placement structure!"))));
|
||||
Component.literal(IrisLanguage.plain(RuntimeUiMessages.DUST_LORE)))));
|
||||
stack.set(DataComponents.UNBREAKABLE, Unit.INSTANCE);
|
||||
stack.set(DataComponents.ENCHANTMENT_GLINT_OVERRIDE, Boolean.TRUE);
|
||||
stack.set(DataComponents.CUSTOM_DATA, CustomData.of(flagTag(DUST_TAG)));
|
||||
@@ -161,7 +164,13 @@ public final class ModdedWandService {
|
||||
return first ? new Selection(dimension, corner, other) : new Selection(dimension, other, corner);
|
||||
});
|
||||
level.playSound(null, pos, SoundEvents.END_PORTAL_FRAME_FILL, SoundSource.PLAYERS, 1.0F, first ? 0.67F : 1.17F);
|
||||
player.sendOverlayMessage(Component.literal("Position " + (first ? 1 : 2) + " set to " + corner.getX() + ", " + corner.getY() + ", " + corner.getZ()));
|
||||
player.sendOverlayMessage(Component.literal(IrisLanguage.plain(
|
||||
RuntimeUiMessages.WAND_POSITION_SET,
|
||||
MessageArgument.trusted("position", first ? 1 : 2),
|
||||
MessageArgument.trusted("x", corner.getX()),
|
||||
MessageArgument.trusted("y", corner.getY()),
|
||||
MessageArgument.trusted("z", corner.getZ())
|
||||
)));
|
||||
}
|
||||
|
||||
public static Selection selection(ServerPlayer player) {
|
||||
|
||||
+43
-40
@@ -51,6 +51,10 @@ import java.util.Locale;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.ModdedCommandMessages;
|
||||
import art.arcane.iris.core.localization.RuntimeUiMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
public final class ModdedWorldCommands {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
@@ -169,13 +173,13 @@ public final class ModdedWorldCommands {
|
||||
if (packFolder.isDirectory()) {
|
||||
return enableInstalled(source, server, dimensionId, pack, packDimension, seed);
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Pack '" + pack + "' is not installed; downloading IrisDimensions/" + pack + "...");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_IS_NOT_INSTALLED_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
Thread thread = new Thread(() -> {
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), pack, "master",
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
server.execute(() -> {
|
||||
if (!installed || !packFolder.isDirectory()) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' could not be downloaded; check the name or install it with /iris download " + pack + ".");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_COULD_NOT_BE_DOWNLOADED_CHECK_NAME_INSTALL_IT_WITH, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
return;
|
||||
}
|
||||
enableInstalled(source, server, dimensionId, pack, packDimension, seed);
|
||||
@@ -197,11 +201,11 @@ public final class ModdedWorldCommands {
|
||||
ModdedDimensionManager.createPersistent(server, dimensionId, pack, packDimension, seed);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris world injection failed for {} (pack={} dim={})", dimensionId, pack, packDimension, e);
|
||||
IrisModdedCommands.fail(source, "Failed to inject Iris world '" + dimensionId + "': " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage()));
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FAILED_INJECT_IRIS_WORLD, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
|
||||
return 0;
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Created Iris world " + dimensionId + " from pack '" + pack + "' dimension '" + packDimension + "' (seed " + seed + ").");
|
||||
IrisModdedCommands.ok(source, "It is live now and re-injected on every startup. Teleport in with /iris world status or a portal; no restart required.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_CREATED_IRIS_WORLD_FROM_PACK_DIMENSION_SEED, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("packDimension", packDimension), MessageArgument.untrusted("seed", seed)));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_IT_IS_LIVE_NOW_RE_INJECTED_ON_EVERY_STARTUP_TELEPORT));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -228,21 +232,21 @@ public final class ModdedWorldCommands {
|
||||
ModdedDimensionManager.createPersistent(server, dimensionId, pack, packDimension, seed);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris primary world injection failed for {} (pack={} dim={})", dimensionId, pack, packDimension, e);
|
||||
IrisModdedCommands.fail(source, "Failed to inject Iris primary world: " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage()));
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FAILED_INJECT_IRIS_PRIMARY_WORLD, MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
|
||||
return 0;
|
||||
}
|
||||
ModdedModConfig.setPrimaryWorld(dimensionId);
|
||||
ModdedPrimaryWorldRouter.clear();
|
||||
IrisModdedCommands.ok(source, "Iris primary world set to " + dimensionId + " (pack '" + pack + "' dimension '" + packDimension + "' seed " + seed + ").");
|
||||
IrisModdedCommands.ok(source, "The vanilla overworld generator cannot be hot-swapped, so this does NOT regenerate the existing overworld.");
|
||||
IrisModdedCommands.ok(source, "Instead, " + dimensionId + " is now the configured primary world: players in the vanilla overworld are routed there on join, and it re-injects on every startup.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_IRIS_PRIMARY_WORLD_SET_PACK_DIMENSION_SEED, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("packDimension", packDimension), MessageArgument.untrusted("seed", seed)));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_VANILLA_OVERWORLD_GENERATOR_CANNOT_BE_HOT_SWAPPED_SO_THIS_DOES));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_INSTEAD_IS_NOW_CONFIGURED_PRIMARY_WORLD_PLAYERS_VANILLA_OVERWORLD_ARE, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int clearMainWorld(CommandSourceStack source) {
|
||||
ModdedModConfig.setMainWorld("", 0L);
|
||||
MainWorldService.clearOverride();
|
||||
IrisModdedCommands.ok(source, "Iris main world override cleared. The overworld keeps its current generator; edit server.properties level-type and restart to change it back.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_IRIS_MAIN_WORLD_OVERRIDE_CLEARED_OVERWORLD_KEEPS_ITS_CURRENT_GENERATOR));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -258,7 +262,7 @@ public final class ModdedWorldCommands {
|
||||
try {
|
||||
seed = Long.parseLong(seedRaw.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
IrisModdedCommands.fail(source, "Invalid seed '" + seedRaw + "'. Use a number or 'random'.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_INVALID_SEED_USE_NUMBER_RANDOM, MessageArgument.untrusted("seedRaw", seedRaw)));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -272,13 +276,13 @@ public final class ModdedWorldCommands {
|
||||
if (packFolder.isDirectory()) {
|
||||
return applyMainWorld(source, pack, packDimension, packRaw, seed);
|
||||
}
|
||||
IrisModdedCommands.ok(source, "Pack '" + pack + "' is not installed; downloading IrisDimensions/" + pack + "...");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_IS_NOT_INSTALLED_DOWNLOADING_IRISDIMENSIONS_2, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
Thread thread = new Thread(() -> {
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), pack, "master",
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
server.execute(() -> {
|
||||
if (!installed || !packFolder.isDirectory()) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' could not be downloaded; check the name or install it with /iris download " + pack + ".");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_COULD_NOT_BE_DOWNLOADED_CHECK_NAME_INSTALL_IT_WITH_2, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
return;
|
||||
}
|
||||
applyMainWorld(source, pack, packDimension, packRaw, seed);
|
||||
@@ -299,23 +303,23 @@ public final class ModdedWorldCommands {
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris main world pack load failed for {} (dim={})", pack, packDimension, e);
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' is not ready yet (still loading or validating). Try the command again in a moment.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_IS_NOT_READY_YET_STILL_LOADING_VALIDATING_TRY_COMMAND, MessageArgument.untrusted("pack", pack)));
|
||||
return 0;
|
||||
}
|
||||
ModdedModConfig.setMainWorld(packRef, seed);
|
||||
if (!MainWorldService.stage(packRef, seed)) {
|
||||
IrisModdedCommands.fail(source, "Failed to write server.properties; check file permissions and set level-type manually.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FAILED_WRITE_SERVER_PROPERTIES_CHECK_FILE_PERMISSIONS_SET_LEVEL_TYPE));
|
||||
return 0;
|
||||
}
|
||||
String preset = MainWorldService.presetIdFor(packRef);
|
||||
IrisModdedCommands.ok(source, "Iris main world set to '" + pack + "' (preset " + preset + ", seed " + (seed == 0L ? "random" : Long.toString(seed)) + ").");
|
||||
IrisModdedCommands.ok(source, "server.properties level-type is now " + preset + ". On the next restart the overworld, nether, and end regenerate as this Iris world.");
|
||||
IrisModdedCommands.ok(source, "Player data (inventories, advancements, stats) is kept; existing terrain in those dimensions is replaced. This applies once.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_IRIS_MAIN_WORLD_SET_PRESET_SEED, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("preset", preset), MessageArgument.untrusted("value", seed == 0L ? IrisLanguage.plain(RuntimeUiMessages.STATUS_RANDOM) : Long.toString(seed))));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_SERVER_PROPERTIES_LEVEL_TYPE_IS_NOW_ON_NEXT_RESTART_OVERWORLD, MessageArgument.untrusted("preset", preset)));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PLAYER_DATA_INVENTORIES_ADVANCEMENTS_STATS_IS_KEPT_EXISTING_TERRAIN_THOSE));
|
||||
if (ModdedModConfig.get().mainWorldAutoRestart()) {
|
||||
IrisModdedCommands.ok(source, "mainWorldAutoRestart is enabled - stopping the server now so your restart wrapper brings it back on the new main world.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_MAINWORLDAUTORESTART_IS_ENABLED_STOPPING_SERVER_NOW_SO_YOUR_RESTART_WRAPPER));
|
||||
source.getServer().halt(false);
|
||||
} else {
|
||||
IrisModdedCommands.ok(source, "Restart the server now to generate it. (Set mainWorldAutoRestart=true in modded.json to have Iris stop the server for you.)");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_RESTART_SERVER_NOW_GENERATE_IT_SET_MAINWORLDAUTORESTART_TRUE_MODDED_JSON));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -325,12 +329,11 @@ public final class ModdedWorldCommands {
|
||||
ModdedStartup.requirePackForWorldCreation(pack);
|
||||
return false;
|
||||
} catch (BrokenPackException e) {
|
||||
IrisModdedCommands.fail(source, "Refusing to create world '" + dimensionId
|
||||
+ "' using pack '" + pack + "' because required validation failed:");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_REFUSING_CREATE_WORLD_USING_PACK_BECAUSE_REQUIRED_VALIDATION_FAILED, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("pack", pack)));
|
||||
for (String reason : e.getReasons()) {
|
||||
IrisModdedCommands.fail(source, " - " + reason);
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_MESSAGE, MessageArgument.untrusted("reason", reason)));
|
||||
}
|
||||
IrisModdedCommands.fail(source, "Fix the pack and run /iris pack validate " + pack + " to revalidate.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FIX_PACK_RUN_IRIS_PACK_VALIDATE_REVALIDATE, MessageArgument.untrusted("pack", pack)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -338,13 +341,13 @@ public final class ModdedWorldCommands {
|
||||
private static boolean loadPackDimension(CommandSourceStack source, String pack, String packDimension) {
|
||||
File packFolder = new File(ModdedPackCommands.packsRoot(), pack);
|
||||
if (!packFolder.isDirectory()) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' was not found under " + ModdedPackCommands.packsRoot().getAbsolutePath());
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_WAS_NOT_FOUND_UNDER, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("value", ModdedPackCommands.packsRoot().getAbsolutePath())));
|
||||
return false;
|
||||
}
|
||||
IrisData data = IrisData.get(packFolder);
|
||||
IrisDimension dimension = data.getDimensionLoader().load(packDimension);
|
||||
if (dimension == null) {
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack + "' does not contain dimensions/" + packDimension + ".json");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_DOES_NOT_CONTAIN_DIMENSIONS_JSON, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("packDimension", packDimension)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -364,7 +367,7 @@ public final class ModdedWorldCommands {
|
||||
&& packDimension.matches("[A-Za-z0-9_/.-]+") && !packDimension.contains("..")) {
|
||||
return true;
|
||||
}
|
||||
IrisModdedCommands.fail(source, "Invalid pack reference '" + pack + (pack.equals(packDimension) ? "" : ":" + packDimension) + "'. Use pack or pack:dimensionKey.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_INVALID_PACK_REFERENCE_USE_PACK_PACK_DIMENSIONKEY, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("value", (pack.equals(packDimension) ? "" : ":" + packDimension))));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -379,7 +382,7 @@ public final class ModdedWorldCommands {
|
||||
try {
|
||||
return Long.parseLong(value);
|
||||
} catch (NumberFormatException e) {
|
||||
IrisModdedCommands.fail(source, "Invalid seed '" + seedRaw + "'. Use a number or 'random'.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_INVALID_SEED_USE_NUMBER_RANDOM_2, MessageArgument.untrusted("seedRaw", seedRaw)));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -398,7 +401,7 @@ public final class ModdedWorldCommands {
|
||||
removed = ModdedDimensionManager.removePersistent(server, dimensionId, wipeStorage);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Iris world removal failed for {}", dimensionId, e);
|
||||
IrisModdedCommands.fail(source, "Failed to remove Iris world '" + dimensionId + "': " + e.getClass().getSimpleName() + (e.getMessage() == null ? "" : " - " + e.getMessage()));
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_FAILED_REMOVE_IRIS_WORLD, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("value", e.getClass().getSimpleName()), MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(e))));
|
||||
return 0;
|
||||
}
|
||||
if (dimensionId.equals(ModdedModConfig.get().primaryWorld())) {
|
||||
@@ -407,17 +410,17 @@ public final class ModdedWorldCommands {
|
||||
}
|
||||
if (!removed) {
|
||||
if (wipeStorage) {
|
||||
IrisModdedCommands.ok(source, "Iris world '" + dimensionId + "' was not loaded; cleared its persistent registry entry and wiped its stored chunk/mantle data.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_IRIS_WORLD_WAS_NOT_LOADED_CLEARED_ITS_PERSISTENT_REGISTRY_ENTRY, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
} else {
|
||||
IrisModdedCommands.ok(source, "Iris world '" + dimensionId + "' was not loaded; cleared its persistent registry entry. World data on disk is kept.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_IRIS_WORLD_WAS_NOT_LOADED_CLEARED_ITS_PERSISTENT_REGISTRY_ENTRY_2, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (wipeStorage) {
|
||||
IrisModdedCommands.ok(source, "Deleted Iris world '" + dimensionId + "': evacuated, unloaded, chunk/mantle data wiped, and dropped from the startup registry.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_DELETED_IRIS_WORLD_EVACUATED_UNLOADED_CHUNK_MANTLE_DATA_WIPED_DROPPED, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
} else {
|
||||
IrisModdedCommands.ok(source, "Disabled Iris world '" + dimensionId + "': evacuated, unloaded, and dropped from the startup registry.");
|
||||
IrisModdedCommands.ok(source, "World data on disk is kept; re-enable with /iris world enable " + dimensionId + " <pack> or delete it with /iris world delete " + dimensionId + ".");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_DISABLED_IRIS_WORLD_EVACUATED_UNLOADED_DROPPED_FROM_STARTUP_REGISTRY, MessageArgument.untrusted("dimensionId", dimensionId)));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_WORLD_DATA_ON_DISK_IS_KEPT_RE_ENABLE_WITH_IRIS, MessageArgument.untrusted("dimensionId", dimensionId), MessageArgument.untrusted("dimensionId2", dimensionId)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -428,27 +431,27 @@ public final class ModdedWorldCommands {
|
||||
for (ServerLevel level : server.getAllLevels()) {
|
||||
if (level.getChunkSource().getGenerator() instanceof IrisModdedChunkGenerator generator) {
|
||||
loaded++;
|
||||
IrisModdedCommands.ok(source, "Loaded Iris level: " + level.dimension().identifier() + " -> pack '" + generator.activePack() + "' dimension '" + generator.activeDimensionKey() + "'");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_LOADED_IRIS_LEVEL_PACK_DIMENSION, MessageArgument.untrusted("value", level.dimension().identifier()), MessageArgument.untrusted("value2", generator.activePack()), MessageArgument.untrusted("value3", generator.activeDimensionKey())));
|
||||
}
|
||||
}
|
||||
String primary = ModdedModConfig.get().primaryWorld();
|
||||
if (!primary.isBlank()) {
|
||||
IrisModdedCommands.ok(source, "Primary world: " + primary + (ModdedModConfig.get().routePlayersToPrimaryWorld() ? " (players routed there)" : " (routing disabled)"));
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PRIMARY_WORLD, MessageArgument.untrusted("primary", primary), MessageArgument.trusted("value", IrisLanguage.plain(ModdedModConfig.get().routePlayersToPrimaryWorld() ? RuntimeUiMessages.PRIMARY_PLAYERS_ROUTED_SUFFIX : RuntimeUiMessages.PRIMARY_ROUTING_DISABLED_SUFFIX))));
|
||||
}
|
||||
if (loaded == 0) {
|
||||
IrisModdedCommands.fail(source, "No Iris dimensions are currently loaded. Create one with /iris world create <name> <pack>.");
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_NO_IRIS_DIMENSIONS_ARE_CURRENTLY_LOADED_CREATE_ONE_WITH_IRIS));
|
||||
}
|
||||
return loaded > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
private static int list(CommandSourceStack source) {
|
||||
List<String> dimensions = loadedIrisDimensions(source.getServer());
|
||||
IrisModdedCommands.ok(source, "Loaded Iris dimensions: " + dimensions.size());
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_LOADED_IRIS_DIMENSIONS, MessageArgument.untrusted("value", dimensions.size())));
|
||||
for (String dimension : dimensions) {
|
||||
IrisModdedCommands.ok(source, " - " + dimension);
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_MESSAGE_2, MessageArgument.untrusted("dimension", dimension)));
|
||||
}
|
||||
if (dimensions.isEmpty()) {
|
||||
IrisModdedCommands.ok(source, "Use /iris world create <name> <pack> to inject one without restarting.");
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_USE_IRIS_WORLD_CREATE_NAME_PACK_INJECT_ONE_WITHOUT_RESTARTING));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+3
@@ -19,6 +19,7 @@
|
||||
package art.arcane.iris.modded.service;
|
||||
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.slf4j.Logger;
|
||||
@@ -52,12 +53,14 @@ public final class ModdedSettingsHotloadService implements ModdedTickableService
|
||||
lastPollAt = now;
|
||||
long modified = settingsFile().lastModified();
|
||||
if (modified == lastModified) {
|
||||
IrisLanguage.update();
|
||||
return;
|
||||
}
|
||||
if (IrisSettings.settings != null) {
|
||||
IrisSettings.invalidate();
|
||||
}
|
||||
IrisSettings.get();
|
||||
IrisLanguage.reload();
|
||||
lastModified = settingsFile().lastModified();
|
||||
LOGGER.info("Hotloaded settings.json");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Vorgenerierungs-HUD umschalten"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Alternar HUD de pregeneración"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Vaihda esigeneroinnin HUD"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Activer ou désactiver le HUD de prégénération"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "הפעלה או כיבוי של תצוגת הקדם-יצירה"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Attiva o disattiva l'HUD di pregenerazione"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "事前生成 HUD の切り替え"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "사전 생성 HUD 전환"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Perjungti išankstinio generavimo HUD"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "HUD voor vooraf genereren in- of uitschakelen"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Przełącz interfejs wstępnego generowania"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Alternar HUD de pré-geração"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Переключить HUD предварительной генерации"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Ön oluşturma HUD'unu aç veya kapat"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "Bật hoặc tắt HUD tạo trước"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "切换预生成 HUD"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"key.categories.irisworldgen.iris": "Iris",
|
||||
"key.irisworldgen.toggle_pregen_hud": "切換預先生成 HUD"
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.volmlib.util.localization.VolmitLocales;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisModLanguageAssetsTest {
|
||||
private static final String ROOT = "assets/irisworldgen/lang/";
|
||||
private static final String TOGGLE_KEY = "key.irisworldgen.toggle_pregen_hud";
|
||||
|
||||
@Test
|
||||
public void minecraftLanguageAssetsMatchSharedLocaleManifest() throws Exception {
|
||||
JsonObject english = read("en_us");
|
||||
assertEquals(2, english.size());
|
||||
|
||||
for (String locale : VolmitLocales.nonEnglish()) {
|
||||
String minecraftLocale = VolmitLocales.minecraftCode(locale);
|
||||
JsonObject translated = read(minecraftLocale);
|
||||
assertEquals(minecraftLocale, english.keySet(), translated.keySet());
|
||||
for (String key : english.keySet()) {
|
||||
JsonElement value = translated.get(key);
|
||||
assertTrue(minecraftLocale + ": " + key, value.isJsonPrimitive());
|
||||
assertTrue(minecraftLocale + ": " + key, value.getAsJsonPrimitive().isString());
|
||||
assertFalse(minecraftLocale + ": " + key, value.getAsString().isBlank());
|
||||
}
|
||||
assertFalse(
|
||||
minecraftLocale + " contains an English HUD label",
|
||||
english.get(TOGGLE_KEY).getAsString().equals(translated.get(TOGGLE_KEY).getAsString())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minecraftLanguageResourceSetMatchesSharedLocaleManifestAndEnglishBaseline() throws Exception {
|
||||
Set<String> expected = VolmitLocales.nonEnglish().stream()
|
||||
.map(VolmitLocales::minecraftCode)
|
||||
.map(locale -> locale + ".json")
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
expected.add("en_us.json");
|
||||
|
||||
assertEquals(expected, resourceFiles());
|
||||
}
|
||||
|
||||
private JsonObject read(String locale) throws Exception {
|
||||
String resource = ROOT + locale + ".json";
|
||||
InputStream input = IrisModLanguageAssetsTest.class.getClassLoader().getResourceAsStream(resource);
|
||||
assertNotNull("Missing mod language asset: " + resource, input);
|
||||
try (InputStream stream = input;
|
||||
InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
|
||||
JsonElement parsed = JsonParser.parseReader(reader);
|
||||
assertTrue("Mod language asset is not an object: " + resource, parsed.isJsonObject());
|
||||
return parsed.getAsJsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> resourceFiles() throws Exception {
|
||||
URL resource = IrisModLanguageAssetsTest.class.getClassLoader().getResource(ROOT);
|
||||
assertNotNull("Missing mod language resource directory", resource);
|
||||
assertEquals("file", resource.getProtocol());
|
||||
try (Stream<Path> paths = Files.list(Path.of(resource.toURI()))) {
|
||||
return paths
|
||||
.filter(Files::isRegularFile)
|
||||
.map(path -> path.getFileName().toString())
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user