209 lines
10 KiB
Java
209 lines
10 KiB
Java
package com.hypixel.hytale.builtin.buildertools.prefabeditor.commands;
|
|
|
|
import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin;
|
|
import com.hypixel.hytale.builtin.buildertools.prefabeditor.PrefabEditSession;
|
|
import com.hypixel.hytale.builtin.buildertools.prefabeditor.PrefabEditSessionManager;
|
|
import com.hypixel.hytale.builtin.buildertools.prefabeditor.PrefabEditingMetadata;
|
|
import com.hypixel.hytale.builtin.buildertools.prefabeditor.saving.PrefabSaver;
|
|
import com.hypixel.hytale.builtin.buildertools.prefabeditor.saving.PrefabSaverSettings;
|
|
import com.hypixel.hytale.common.util.PathUtil;
|
|
import com.hypixel.hytale.component.Ref;
|
|
import com.hypixel.hytale.component.Store;
|
|
import com.hypixel.hytale.server.core.Message;
|
|
import com.hypixel.hytale.server.core.command.system.CommandContext;
|
|
import com.hypixel.hytale.server.core.command.system.arguments.system.FlagArg;
|
|
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractAsyncPlayerCommand;
|
|
import com.hypixel.hytale.server.core.entity.entities.Player;
|
|
import com.hypixel.hytale.server.core.modules.singleplayer.SingleplayerModule;
|
|
import com.hypixel.hytale.server.core.prefab.PrefabStore;
|
|
import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection;
|
|
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
|
import com.hypixel.hytale.server.core.universe.world.World;
|
|
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
|
import java.nio.file.Path;
|
|
import java.util.List;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import javax.annotation.Nonnull;
|
|
|
|
public class PrefabEditSaveCommand extends AbstractAsyncPlayerCommand {
|
|
@Nonnull
|
|
private static final Message MESSAGE_COMMANDS_EDIT_PREFAB_NOT_IN_EDIT_SESSION = Message.translation("server.commands.editprefab.notInEditSession");
|
|
@Nonnull
|
|
private static final Message MESSAGE_PATH_OUTSIDE_PREFABS_DIR = Message.translation("server.builderTools.attemptedToSaveOutsidePrefabsDir");
|
|
@Nonnull
|
|
private final FlagArg saveAllArg = this.withFlagArg("saveAll", "server.commands.editprefab.save.saveAll.desc").addAliases("all");
|
|
@Nonnull
|
|
private final FlagArg noEntitiesArg = this.withFlagArg("noEntities", "server.commands.editprefab.save.noEntities.desc");
|
|
@Nonnull
|
|
private final FlagArg emptyArg = this.withFlagArg("empty", "server.commands.editprefab.save.empty.desc");
|
|
@Nonnull
|
|
private final FlagArg confirmArg = this.withFlagArg("confirm", "server.commands.editprefab.save.confirm.desc");
|
|
|
|
private static boolean isPathInAllowedPrefabDirectory(@Nonnull Path path) {
|
|
PrefabStore prefabStore = PrefabStore.get();
|
|
return PathUtil.isChildOf(prefabStore.getServerPrefabsPath(), path)
|
|
|| PathUtil.isChildOf(prefabStore.getAssetPrefabsPath(), path)
|
|
|| PathUtil.isChildOf(prefabStore.getWorldGenPrefabsPath(), path);
|
|
}
|
|
|
|
public PrefabEditSaveCommand() {
|
|
super("save", "server.commands.editprefab.save.desc");
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
protected CompletableFuture<Void> executeAsync(
|
|
@Nonnull CommandContext context, @Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref, @Nonnull PlayerRef playerRef, @Nonnull World world
|
|
) {
|
|
Player playerComponent = store.getComponent(ref, Player.getComponentType());
|
|
|
|
assert playerComponent != null;
|
|
|
|
PrefabEditSessionManager prefabEditSessionManager = BuilderToolsPlugin.get().getPrefabEditSessionManager();
|
|
PrefabEditSession prefabEditSession = prefabEditSessionManager.getPrefabEditSession(playerRef.getUuid());
|
|
if (prefabEditSession == null) {
|
|
context.sendMessage(MESSAGE_COMMANDS_EDIT_PREFAB_NOT_IN_EDIT_SESSION);
|
|
return CompletableFuture.completedFuture(null);
|
|
} else {
|
|
PrefabSaverSettings prefabSaverSettings = new PrefabSaverSettings();
|
|
prefabSaverSettings.setBlocks(true);
|
|
prefabSaverSettings.setEntities(!this.noEntitiesArg.provided(context));
|
|
prefabSaverSettings.setOverwriteExisting(true);
|
|
prefabSaverSettings.setEmpty(this.emptyArg.get(context));
|
|
boolean confirm = this.confirmArg.provided(context);
|
|
if (!this.saveAllArg.provided(context)) {
|
|
PrefabEditingMetadata selectedPrefab = prefabEditSession.getSelectedPrefab(playerRef.getUuid());
|
|
if (selectedPrefab == null) {
|
|
context.sendMessage(Message.translation("server.commands.editprefab.noPrefabSelected"));
|
|
return CompletableFuture.completedFuture(null);
|
|
} else if (selectedPrefab.isReadOnly() && !confirm) {
|
|
Path redirectPath = getWritableSavePath(selectedPrefab, true);
|
|
context.sendMessage(
|
|
Message.translation("server.commands.editprefab.save.readOnlyNeedsConfirmSingle")
|
|
.param("path", selectedPrefab.getPrefabPath().toString())
|
|
.param("redirectPath", redirectPath.toString())
|
|
);
|
|
return CompletableFuture.completedFuture(null);
|
|
} else {
|
|
BlockSelection selection = BuilderToolsPlugin.getState(playerComponent, playerRef).getSelection();
|
|
if (selectedPrefab.getMinPoint().equals(selection.getSelectionMin()) && selectedPrefab.getMaxPoint().equals(selection.getSelectionMax())) {
|
|
Path savePath = getWritableSavePath(selectedPrefab, confirm);
|
|
if (!SingleplayerModule.isOwner(playerRef) && !isPathInAllowedPrefabDirectory(savePath)) {
|
|
context.sendMessage(MESSAGE_PATH_OUTSIDE_PREFABS_DIR);
|
|
return CompletableFuture.completedFuture(null);
|
|
} else {
|
|
return PrefabSaver.savePrefab(
|
|
playerComponent,
|
|
world,
|
|
savePath,
|
|
selectedPrefab.getAnchorPoint(),
|
|
selectedPrefab.getMinPoint(),
|
|
selectedPrefab.getMaxPoint(),
|
|
selectedPrefab.getPastePosition(),
|
|
selectedPrefab.getOriginalFileAnchor(),
|
|
prefabSaverSettings
|
|
)
|
|
.thenAccept(
|
|
success -> {
|
|
if (success) {
|
|
selectedPrefab.setDirty(false);
|
|
}
|
|
|
|
context.sendMessage(
|
|
Message.translation("server.commands.editprefab.save." + (success ? "success" : "failure")).param("name", savePath.toString())
|
|
);
|
|
}
|
|
);
|
|
}
|
|
} else {
|
|
context.sendMessage(Message.translation("server.commands.editprefab.save.selectionMismatch"));
|
|
return CompletableFuture.completedFuture(null);
|
|
}
|
|
}
|
|
} else {
|
|
PrefabEditingMetadata[] values = prefabEditSession.getLoadedPrefabMetadata().values().toArray(new PrefabEditingMetadata[0]);
|
|
int readOnlyCount = 0;
|
|
|
|
for (PrefabEditingMetadata value : values) {
|
|
if (value.isReadOnly()) {
|
|
readOnlyCount++;
|
|
}
|
|
}
|
|
|
|
if (readOnlyCount > 0 && !confirm) {
|
|
context.sendMessage(Message.translation("server.commands.editprefab.save.readOnlyNeedsConfirm").param("count", readOnlyCount));
|
|
return CompletableFuture.completedFuture(null);
|
|
} else {
|
|
if (!SingleplayerModule.isOwner(playerRef)) {
|
|
for (PrefabEditingMetadata valuex : values) {
|
|
Path savePath = getWritableSavePath(valuex, confirm);
|
|
if (!isPathInAllowedPrefabDirectory(savePath)) {
|
|
context.sendMessage(MESSAGE_PATH_OUTSIDE_PREFABS_DIR);
|
|
return CompletableFuture.completedFuture(null);
|
|
}
|
|
}
|
|
}
|
|
|
|
context.sendMessage(Message.translation("server.commands.editprefab.save.saveAll.start").param("amount", values.length));
|
|
CompletableFuture<Boolean>[] prefabSavingFutures = new CompletableFuture[values.length];
|
|
|
|
for (int i = 0; i < values.length; i++) {
|
|
PrefabEditingMetadata valuexx = values[i];
|
|
Path savePath = getWritableSavePath(valuexx, confirm);
|
|
prefabSavingFutures[i] = PrefabSaver.savePrefab(
|
|
playerComponent,
|
|
world,
|
|
savePath,
|
|
valuexx.getAnchorPoint(),
|
|
valuexx.getMinPoint(),
|
|
valuexx.getMaxPoint(),
|
|
valuexx.getPastePosition(),
|
|
valuexx.getOriginalFileAnchor(),
|
|
prefabSaverSettings
|
|
);
|
|
}
|
|
|
|
return CompletableFuture.allOf(prefabSavingFutures)
|
|
.thenAccept(
|
|
unused -> {
|
|
List<Integer> failedPrefabFutures = new IntArrayList();
|
|
|
|
for (int i1 = 0; i1 < prefabSavingFutures.length; i1++) {
|
|
if (prefabSavingFutures[i1].join()) {
|
|
values[i1].setDirty(false);
|
|
} else {
|
|
failedPrefabFutures.add(i1);
|
|
}
|
|
}
|
|
|
|
context.sendMessage(
|
|
Message.translation("server.commands.editprefab.save.saveAll.success")
|
|
.param("successes", prefabSavingFutures.length - failedPrefabFutures.size())
|
|
.param("failures", failedPrefabFutures.size())
|
|
);
|
|
}
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
private static Path getWritableSavePath(@Nonnull PrefabEditingMetadata metadata, boolean confirm) {
|
|
if (metadata.isReadOnly() && confirm) {
|
|
Path originalPath = metadata.getPrefabPath();
|
|
String fileName = originalPath.getFileName().toString();
|
|
Path parent = originalPath.getParent();
|
|
if (parent != null && parent.getFileName() != null) {
|
|
String parentName = parent.getFileName().toString();
|
|
return PrefabStore.get().getServerPrefabsPath().resolve(parentName).resolve(fileName);
|
|
} else {
|
|
return PrefabStore.get().getServerPrefabsPath().resolve(fileName);
|
|
}
|
|
} else {
|
|
return metadata.getPrefabPath();
|
|
}
|
|
}
|
|
}
|