582 lines
27 KiB
Java
582 lines
27 KiB
Java
package com.hypixel.hytale.builtin.buildertools.imageimport;
|
|
|
|
import com.hypixel.hytale.builtin.buildertools.BlockColorIndex;
|
|
import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin;
|
|
import com.hypixel.hytale.codec.Codec;
|
|
import com.hypixel.hytale.codec.KeyedCodec;
|
|
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
|
import com.hypixel.hytale.common.util.StringUtil;
|
|
import com.hypixel.hytale.component.Ref;
|
|
import com.hypixel.hytale.component.Store;
|
|
import com.hypixel.hytale.logger.HytaleLogger;
|
|
import com.hypixel.hytale.math.vector.Vector3i;
|
|
import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
|
|
import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType;
|
|
import com.hypixel.hytale.protocol.packets.interface_.Page;
|
|
import com.hypixel.hytale.protocol.packets.inventory.SetActiveSlot;
|
|
import com.hypixel.hytale.server.core.Message;
|
|
import com.hypixel.hytale.server.core.entity.entities.Player;
|
|
import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage;
|
|
import com.hypixel.hytale.server.core.inventory.Inventory;
|
|
import com.hypixel.hytale.server.core.inventory.ItemStack;
|
|
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
|
|
import com.hypixel.hytale.server.core.modules.singleplayer.SingleplayerModule;
|
|
import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection;
|
|
import com.hypixel.hytale.server.core.ui.DropdownEntryInfo;
|
|
import com.hypixel.hytale.server.core.ui.LocalizableString;
|
|
import com.hypixel.hytale.server.core.ui.browser.FileBrowserConfig;
|
|
import com.hypixel.hytale.server.core.ui.browser.ServerFileBrowser;
|
|
import com.hypixel.hytale.server.core.ui.builder.EventData;
|
|
import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
|
|
import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
|
|
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
|
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.logging.Level;
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
import javax.imageio.ImageIO;
|
|
|
|
public class ImageImportPage extends InteractiveCustomUIPage<ImageImportPage.PageData> {
|
|
private static final int DEFAULT_MAX_SIZE = 128;
|
|
private static final int MIN_SIZE = 1;
|
|
private static final int MAX_SIZE = 512;
|
|
private static final String PASTE_TOOL_ID = "EditorTool_Paste";
|
|
private static final Path IMPORTS_DIR = Paths.get("imports", "images");
|
|
@Nonnull
|
|
private String imagePath = "";
|
|
private int maxDimension = 128;
|
|
@Nonnull
|
|
private String orientationStr = "wall_xy";
|
|
@Nonnull
|
|
private ImageImportPage.Orientation orientation = ImageImportPage.Orientation.VERTICAL_XY;
|
|
@Nonnull
|
|
private String originStr = "bottom_center";
|
|
@Nonnull
|
|
private ImageImportPage.Origin origin = ImageImportPage.Origin.BOTTOM_CENTER;
|
|
@Nullable
|
|
private String statusMessage = null;
|
|
private boolean isError = false;
|
|
private boolean isProcessing = false;
|
|
private boolean showBrowser = false;
|
|
@Nonnull
|
|
private final ServerFileBrowser browser;
|
|
|
|
public ImageImportPage(@Nonnull PlayerRef playerRef) {
|
|
super(playerRef, CustomPageLifetime.CanDismiss, ImageImportPage.PageData.CODEC);
|
|
FileBrowserConfig config = FileBrowserConfig.builder()
|
|
.listElementId("#BrowserPage #FileList")
|
|
.searchInputId("#BrowserPage #SearchInput")
|
|
.currentPathId("#BrowserPage #CurrentPath")
|
|
.roots(List.of(new FileBrowserConfig.RootEntry("Imports", IMPORTS_DIR)))
|
|
.allowedExtensions(".png", ".jpg", ".jpeg", ".gif", ".bmp")
|
|
.enableRootSelector(false)
|
|
.enableSearch(true)
|
|
.enableDirectoryNav(true)
|
|
.maxResults(50)
|
|
.build();
|
|
|
|
try {
|
|
Files.createDirectories(IMPORTS_DIR);
|
|
} catch (IOException var4) {
|
|
}
|
|
|
|
this.browser = new ServerFileBrowser(config);
|
|
}
|
|
|
|
@Override
|
|
public void build(
|
|
@Nonnull Ref<EntityStore> ref, @Nonnull UICommandBuilder commandBuilder, @Nonnull UIEventBuilder eventBuilder, @Nonnull Store<EntityStore> store
|
|
) {
|
|
commandBuilder.append("Pages/ImageImportPage.ui");
|
|
commandBuilder.set("#ImagePath #Input.Value", this.imagePath);
|
|
commandBuilder.set("#MaxSizeInput #Input.Value", this.maxDimension);
|
|
List<DropdownEntryInfo> orientationEntries = new ArrayList<>();
|
|
orientationEntries.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.imageImport.orientation.wall_xy"), "wall_xy"));
|
|
orientationEntries.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.imageImport.orientation.wall_xz"), "wall_xz"));
|
|
orientationEntries.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.imageImport.orientation.floor"), "floor"));
|
|
commandBuilder.set("#OrientationInput #Input.Entries", orientationEntries);
|
|
commandBuilder.set("#OrientationInput #Input.Value", this.orientationStr);
|
|
List<DropdownEntryInfo> originEntries = new ArrayList<>();
|
|
originEntries.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.bottom_front_left"), "bottom_front_left"));
|
|
originEntries.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.bottom_center"), "bottom_center"));
|
|
originEntries.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.center"), "center"));
|
|
originEntries.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.top_center"), "top_center"));
|
|
commandBuilder.set("#OriginInput #Input.Entries", originEntries);
|
|
commandBuilder.set("#OriginInput #Input.Value", this.originStr);
|
|
this.updateStatus(commandBuilder);
|
|
eventBuilder.addEventBinding(CustomUIEventBindingType.ValueChanged, "#ImagePath #Input", EventData.of("@ImagePath", "#ImagePath #Input.Value"), false);
|
|
eventBuilder.addEventBinding(CustomUIEventBindingType.ValueChanged, "#MaxSizeInput #Input", EventData.of("@MaxSize", "#MaxSizeInput #Input.Value"), false);
|
|
eventBuilder.addEventBinding(
|
|
CustomUIEventBindingType.ValueChanged, "#OrientationInput #Input", EventData.of("@Orientation", "#OrientationInput #Input.Value"), false
|
|
);
|
|
eventBuilder.addEventBinding(CustomUIEventBindingType.ValueChanged, "#OriginInput #Input", EventData.of("@Origin", "#OriginInput #Input.Value"), false);
|
|
eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#ImportButton", EventData.of("Import", "true"));
|
|
eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#ImagePath #BrowseButton", EventData.of("Browse", "true"));
|
|
commandBuilder.set("#FormContainer.Visible", !this.showBrowser);
|
|
commandBuilder.set("#BrowserPage.Visible", this.showBrowser);
|
|
if (this.showBrowser) {
|
|
this.buildBrowserPage(commandBuilder, eventBuilder);
|
|
}
|
|
}
|
|
|
|
private void buildBrowserPage(@Nonnull UICommandBuilder commandBuilder, @Nonnull UIEventBuilder eventBuilder) {
|
|
this.browser.buildSearchInput(commandBuilder, eventBuilder);
|
|
this.browser.buildCurrentPath(commandBuilder);
|
|
this.browser.buildFileList(commandBuilder, eventBuilder);
|
|
eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#BrowserPage #SelectButton", EventData.of("BrowserSelect", "true"));
|
|
eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#BrowserPage #CancelButton", EventData.of("BrowserCancel", "true"));
|
|
}
|
|
|
|
private void updateStatus(@Nonnull UICommandBuilder commandBuilder) {
|
|
if (this.statusMessage != null) {
|
|
commandBuilder.set("#StatusText.Text", this.statusMessage);
|
|
commandBuilder.set("#StatusText.Visible", true);
|
|
commandBuilder.set("#StatusText.Style.TextColor", this.isError ? "#e74c3c" : "#cfd8e3");
|
|
} else {
|
|
commandBuilder.set("#StatusText.Visible", false);
|
|
}
|
|
}
|
|
|
|
private void setError(@Nonnull String message) {
|
|
this.statusMessage = message;
|
|
this.isError = true;
|
|
this.isProcessing = false;
|
|
this.rebuild();
|
|
}
|
|
|
|
private void setStatus(@Nonnull String message) {
|
|
this.statusMessage = message;
|
|
this.isError = false;
|
|
this.rebuild();
|
|
}
|
|
|
|
public void handleDataEvent(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store, @Nonnull ImageImportPage.PageData data) {
|
|
boolean needsUpdate = false;
|
|
if (data.browse != null && data.browse) {
|
|
this.showBrowser = true;
|
|
this.rebuild();
|
|
} else if (data.browserCancel != null && data.browserCancel) {
|
|
this.showBrowser = false;
|
|
this.rebuild();
|
|
} else if (data.browserSelect != null && data.browserSelect) {
|
|
if (!this.browser.getSelectedItems().isEmpty()) {
|
|
String selectedPath = this.browser.getSelectedItems().iterator().next();
|
|
this.imagePath = this.browser.getRoot().resolve(selectedPath).toString();
|
|
}
|
|
|
|
this.showBrowser = false;
|
|
this.rebuild();
|
|
} else {
|
|
if (this.showBrowser && (data.file != null || data.searchQuery != null || data.searchResult != null)) {
|
|
boolean handled = false;
|
|
if (data.searchQuery != null) {
|
|
this.browser.setSearchQuery(data.searchQuery.trim().toLowerCase());
|
|
handled = true;
|
|
}
|
|
|
|
if (data.file != null) {
|
|
String fileName = data.file;
|
|
if ("..".equals(fileName)) {
|
|
this.browser.navigateUp();
|
|
handled = true;
|
|
} else {
|
|
Path targetPath = this.browser.resolveFromCurrent(fileName);
|
|
if (targetPath != null && Files.isDirectory(targetPath)) {
|
|
this.browser.navigateTo(Paths.get(fileName));
|
|
handled = true;
|
|
} else if (targetPath != null && Files.isRegularFile(targetPath)) {
|
|
this.imagePath = targetPath.toString();
|
|
this.showBrowser = false;
|
|
this.rebuild();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (data.searchResult != null) {
|
|
Path resolvedPath = this.browser.resolveSecure(data.searchResult);
|
|
if (resolvedPath != null && Files.isRegularFile(resolvedPath)) {
|
|
this.imagePath = resolvedPath.toString();
|
|
this.showBrowser = false;
|
|
this.rebuild();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (handled) {
|
|
UICommandBuilder commandBuilder = new UICommandBuilder();
|
|
UIEventBuilder eventBuilder = new UIEventBuilder();
|
|
this.browser.buildFileList(commandBuilder, eventBuilder);
|
|
this.browser.buildCurrentPath(commandBuilder);
|
|
this.sendUpdate(commandBuilder, eventBuilder, false);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (data.imagePath != null) {
|
|
this.imagePath = StringUtil.stripQuotes(data.imagePath.trim());
|
|
this.statusMessage = null;
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (data.maxSize != null) {
|
|
this.maxDimension = Math.max(1, Math.min(512, data.maxSize));
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (data.orientation != null) {
|
|
this.orientationStr = data.orientation.trim().toLowerCase();
|
|
String var8 = this.orientationStr;
|
|
|
|
this.orientation = switch (var8) {
|
|
case "wall_xz", "xz", "vertical_xz" -> ImageImportPage.Orientation.VERTICAL_XZ;
|
|
case "floor", "horizontal", "horizontal_xz" -> ImageImportPage.Orientation.HORIZONTAL_XZ;
|
|
default -> ImageImportPage.Orientation.VERTICAL_XY;
|
|
};
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (data.origin != null) {
|
|
this.originStr = data.origin.trim().toLowerCase();
|
|
String var9 = this.originStr;
|
|
|
|
this.origin = switch (var9) {
|
|
case "bottom_front_left" -> ImageImportPage.Origin.BOTTOM_FRONT_LEFT;
|
|
case "center" -> ImageImportPage.Origin.CENTER;
|
|
case "top_center" -> ImageImportPage.Origin.TOP_CENTER;
|
|
default -> ImageImportPage.Origin.BOTTOM_CENTER;
|
|
};
|
|
needsUpdate = true;
|
|
}
|
|
|
|
if (data.doImport != null && data.doImport && !this.isProcessing) {
|
|
this.performImport(ref, store);
|
|
} else {
|
|
if (needsUpdate) {
|
|
this.sendUpdate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void performImport(@Nonnull Ref<EntityStore> ref, @Nonnull Store<EntityStore> store) {
|
|
if (this.imagePath.isEmpty()) {
|
|
this.setError("Please enter a path to an image file");
|
|
} else {
|
|
Path path = Paths.get(this.imagePath);
|
|
if (!SingleplayerModule.isOwner(this.playerRef)) {
|
|
Path normalizedPath = path.toAbsolutePath().normalize();
|
|
Path normalizedImports = IMPORTS_DIR.toAbsolutePath().normalize();
|
|
if (!normalizedPath.startsWith(normalizedImports)) {
|
|
this.setError("Files must be in the server's imports/images directory");
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!Files.exists(path)) {
|
|
this.setError("File not found: " + this.imagePath);
|
|
} else {
|
|
this.isProcessing = true;
|
|
this.setStatus("Processing...");
|
|
Player playerComponent = store.getComponent(ref, Player.getComponentType());
|
|
PlayerRef playerRefComponent = store.getComponent(ref, PlayerRef.getComponentType());
|
|
if (playerComponent != null && playerRefComponent != null) {
|
|
String finalPath = this.imagePath;
|
|
int finalMaxSize = this.maxDimension;
|
|
ImageImportPage.Orientation finalOrientation = this.orientation;
|
|
ImageImportPage.Origin finalOrigin = this.origin;
|
|
BuilderToolsPlugin.addToQueue(
|
|
playerComponent,
|
|
playerRefComponent,
|
|
(r, builderState, componentAccessor) -> {
|
|
try {
|
|
BufferedImage image = null;
|
|
|
|
try {
|
|
image = ImageIO.read(Paths.get(finalPath).toFile());
|
|
} catch (Exception var38) {
|
|
}
|
|
|
|
if (image == null) {
|
|
this.setError("Unable to read image file (unsupported format or corrupted). Try PNG format.");
|
|
return;
|
|
}
|
|
|
|
int width = image.getWidth();
|
|
int height = image.getHeight();
|
|
float scale = 1.0F;
|
|
if (width > finalMaxSize || height > finalMaxSize) {
|
|
scale = (float)finalMaxSize / Math.max(width, height);
|
|
width = Math.round(width * scale);
|
|
height = Math.round(height * scale);
|
|
}
|
|
|
|
BlockColorIndex colorIndex = BuilderToolsPlugin.get().getBlockColorIndex();
|
|
if (colorIndex.isEmpty()) {
|
|
this.setError("Block color index not initialized");
|
|
return;
|
|
}
|
|
|
|
int sizeX;
|
|
int sizeY;
|
|
int sizeZ;
|
|
switch (finalOrientation) {
|
|
case VERTICAL_XY:
|
|
sizeX = width;
|
|
sizeY = height;
|
|
sizeZ = 1;
|
|
break;
|
|
case VERTICAL_XZ:
|
|
sizeX = width;
|
|
sizeY = 1;
|
|
sizeZ = height;
|
|
break;
|
|
case HORIZONTAL_XZ:
|
|
sizeX = width;
|
|
sizeY = 1;
|
|
sizeZ = height;
|
|
break;
|
|
default:
|
|
sizeX = width;
|
|
sizeY = height;
|
|
sizeZ = 1;
|
|
}
|
|
|
|
int offsetX = 0;
|
|
int offsetY = 0;
|
|
int offsetZ = 0;
|
|
switch (finalOrigin) {
|
|
case BOTTOM_FRONT_LEFT:
|
|
default:
|
|
break;
|
|
case BOTTOM_CENTER:
|
|
offsetX = -sizeX / 2;
|
|
offsetZ = -sizeZ / 2;
|
|
break;
|
|
case CENTER:
|
|
offsetX = -sizeX / 2;
|
|
offsetY = -sizeY / 2;
|
|
offsetZ = -sizeZ / 2;
|
|
break;
|
|
case TOP_CENTER:
|
|
offsetX = -sizeX / 2;
|
|
offsetY = -sizeY;
|
|
offsetZ = -sizeZ / 2;
|
|
}
|
|
|
|
BlockSelection selection = new BlockSelection(width * height, 0);
|
|
selection.setPosition(0, 0, 0);
|
|
int blockCount = 0;
|
|
float finalScale = scale;
|
|
|
|
for (int imgY = 0; imgY < height; imgY++) {
|
|
for (int imgX = 0; imgX < width; imgX++) {
|
|
int srcX = Math.min((int)(imgX / finalScale), image.getWidth() - 1);
|
|
int srcY = Math.min((int)(imgY / finalScale), image.getHeight() - 1);
|
|
int rgba = image.getRGB(srcX, srcY);
|
|
int alpha = rgba >> 24 & 0xFF;
|
|
if (alpha >= 128) {
|
|
int red = rgba >> 16 & 0xFF;
|
|
int green = rgba >> 8 & 0xFF;
|
|
int blue = rgba & 0xFF;
|
|
int blockId = colorIndex.findClosestBlock(red, green, blue);
|
|
if (blockId > 0) {
|
|
int blockX;
|
|
int blockY;
|
|
int blockZ;
|
|
switch (finalOrientation) {
|
|
case VERTICAL_XY:
|
|
blockX = imgX;
|
|
blockY = height - 1 - imgY;
|
|
blockZ = 0;
|
|
break;
|
|
case VERTICAL_XZ:
|
|
blockX = imgX;
|
|
blockY = 0;
|
|
blockZ = height - 1 - imgY;
|
|
break;
|
|
case HORIZONTAL_XZ:
|
|
blockX = imgX;
|
|
blockY = 0;
|
|
blockZ = imgY;
|
|
break;
|
|
default:
|
|
blockX = imgX;
|
|
blockY = height - 1 - imgY;
|
|
blockZ = 0;
|
|
}
|
|
|
|
selection.addBlockAtLocalPos(blockX + offsetX, blockY + offsetY, blockZ + offsetZ, blockId, 0, 0, 0);
|
|
blockCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
selection.setSelectionArea(
|
|
new Vector3i(offsetX, offsetY, offsetZ), new Vector3i(sizeX - 1 + offsetX, sizeY - 1 + offsetY, sizeZ - 1 + offsetZ)
|
|
);
|
|
builderState.setSelection(selection);
|
|
builderState.sendSelectionToClient();
|
|
this.statusMessage = String.format("Success! %d blocks copied to clipboard (%dx%dx%d)", blockCount, sizeX, sizeY, sizeZ);
|
|
this.isProcessing = false;
|
|
playerRefComponent.sendMessage(
|
|
Message.translation("server.builderTools.imageImport.success")
|
|
.param("count", blockCount)
|
|
.param("width", sizeX)
|
|
.param("height", sizeY)
|
|
.param("depth", sizeZ)
|
|
);
|
|
playerComponent.getPageManager().setPage(r, store, Page.None);
|
|
this.switchToPasteTool(playerComponent, playerRefComponent);
|
|
} catch (Exception var39) {
|
|
((HytaleLogger.Api)BuilderToolsPlugin.get().getLogger().at(Level.WARNING).withCause(var39)).log("Image import error");
|
|
this.setError("Error: " + var39.getMessage());
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
this.setError("Player not found");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void switchToPasteTool(@Nonnull Player playerComponent, @Nonnull PlayerRef playerRef) {
|
|
Inventory inventory = playerComponent.getInventory();
|
|
ItemContainer hotbar = inventory.getHotbar();
|
|
ItemContainer storage = inventory.getStorage();
|
|
ItemContainer tools = inventory.getTools();
|
|
int hotbarSize = hotbar.getCapacity();
|
|
|
|
for (short slot = 0; slot < hotbarSize; slot++) {
|
|
ItemStack itemStack = hotbar.getItemStack(slot);
|
|
if (itemStack != null && !itemStack.isEmpty() && "EditorTool_Paste".equals(itemStack.getItemId())) {
|
|
inventory.setActiveHotbarSlot((byte)slot);
|
|
playerRef.getPacketHandler().writeNoCache(new SetActiveSlot(-1, (byte)slot));
|
|
return;
|
|
}
|
|
}
|
|
|
|
short emptySlot = -1;
|
|
|
|
for (short slotx = 0; slotx < hotbarSize; slotx++) {
|
|
ItemStack itemStack = hotbar.getItemStack(slotx);
|
|
if (itemStack == null || itemStack.isEmpty()) {
|
|
emptySlot = slotx;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (emptySlot != -1) {
|
|
for (short slotxx = 0; slotxx < storage.getCapacity(); slotxx++) {
|
|
ItemStack itemStack = storage.getItemStack(slotxx);
|
|
if (itemStack != null && !itemStack.isEmpty() && "EditorTool_Paste".equals(itemStack.getItemId())) {
|
|
storage.moveItemStackFromSlotToSlot(slotxx, 1, hotbar, emptySlot);
|
|
inventory.setActiveHotbarSlot((byte)emptySlot);
|
|
playerRef.getPacketHandler().writeNoCache(new SetActiveSlot(-1, (byte)emptySlot));
|
|
return;
|
|
}
|
|
}
|
|
|
|
ItemStack pasteToolStack = null;
|
|
|
|
for (short slotxxx = 0; slotxxx < tools.getCapacity(); slotxxx++) {
|
|
ItemStack itemStack = tools.getItemStack(slotxxx);
|
|
if (itemStack != null && !itemStack.isEmpty() && "EditorTool_Paste".equals(itemStack.getItemId())) {
|
|
pasteToolStack = itemStack;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pasteToolStack != null) {
|
|
hotbar.setItemStackForSlot(emptySlot, new ItemStack(pasteToolStack.getItemId()));
|
|
inventory.setActiveHotbarSlot((byte)emptySlot);
|
|
playerRef.getPacketHandler().writeNoCache(new SetActiveSlot(-1, (byte)emptySlot));
|
|
}
|
|
}
|
|
}
|
|
|
|
public static enum Orientation {
|
|
VERTICAL_XY,
|
|
VERTICAL_XZ,
|
|
HORIZONTAL_XZ;
|
|
}
|
|
|
|
public static enum Origin {
|
|
BOTTOM_FRONT_LEFT,
|
|
BOTTOM_CENTER,
|
|
CENTER,
|
|
TOP_CENTER;
|
|
}
|
|
|
|
public static class PageData {
|
|
static final String KEY_IMAGE_PATH = "@ImagePath";
|
|
static final String KEY_MAX_SIZE = "@MaxSize";
|
|
static final String KEY_ORIENTATION = "@Orientation";
|
|
static final String KEY_ORIGIN = "@Origin";
|
|
static final String KEY_IMPORT = "Import";
|
|
static final String KEY_BROWSE = "Browse";
|
|
static final String KEY_BROWSER_SELECT = "BrowserSelect";
|
|
static final String KEY_BROWSER_CANCEL = "BrowserCancel";
|
|
public static final BuilderCodec<ImageImportPage.PageData> CODEC = BuilderCodec.builder(ImageImportPage.PageData.class, ImageImportPage.PageData::new)
|
|
.addField(new KeyedCodec<>("@ImagePath", Codec.STRING), (entry, s) -> entry.imagePath = s, entry -> entry.imagePath)
|
|
.addField(new KeyedCodec<>("@MaxSize", Codec.INTEGER), (entry, i) -> entry.maxSize = i, entry -> entry.maxSize)
|
|
.addField(new KeyedCodec<>("@Orientation", Codec.STRING), (entry, s) -> entry.orientation = s, entry -> entry.orientation)
|
|
.addField(new KeyedCodec<>("@Origin", Codec.STRING), (entry, s) -> entry.origin = s, entry -> entry.origin)
|
|
.addField(
|
|
new KeyedCodec<>("Import", Codec.STRING),
|
|
(entry, s) -> entry.doImport = "true".equalsIgnoreCase(s),
|
|
entry -> entry.doImport != null && entry.doImport ? "true" : null
|
|
)
|
|
.addField(
|
|
new KeyedCodec<>("Browse", Codec.STRING),
|
|
(entry, s) -> entry.browse = "true".equalsIgnoreCase(s),
|
|
entry -> entry.browse != null && entry.browse ? "true" : null
|
|
)
|
|
.addField(
|
|
new KeyedCodec<>("BrowserSelect", Codec.STRING),
|
|
(entry, s) -> entry.browserSelect = "true".equalsIgnoreCase(s),
|
|
entry -> entry.browserSelect != null && entry.browserSelect ? "true" : null
|
|
)
|
|
.addField(
|
|
new KeyedCodec<>("BrowserCancel", Codec.STRING),
|
|
(entry, s) -> entry.browserCancel = "true".equalsIgnoreCase(s),
|
|
entry -> entry.browserCancel != null && entry.browserCancel ? "true" : null
|
|
)
|
|
.addField(new KeyedCodec<>("File", Codec.STRING), (entry, s) -> entry.file = s, entry -> entry.file)
|
|
.addField(new KeyedCodec<>("@SearchQuery", Codec.STRING), (entry, s) -> entry.searchQuery = s, entry -> entry.searchQuery)
|
|
.addField(new KeyedCodec<>("SearchResult", Codec.STRING), (entry, s) -> entry.searchResult = s, entry -> entry.searchResult)
|
|
.build();
|
|
@Nullable
|
|
private String imagePath;
|
|
@Nullable
|
|
private Integer maxSize;
|
|
@Nullable
|
|
private String orientation;
|
|
@Nullable
|
|
private String origin;
|
|
@Nullable
|
|
private Boolean doImport;
|
|
@Nullable
|
|
private Boolean browse;
|
|
@Nullable
|
|
private Boolean browserSelect;
|
|
@Nullable
|
|
private Boolean browserCancel;
|
|
@Nullable
|
|
private String file;
|
|
@Nullable
|
|
private String searchQuery;
|
|
@Nullable
|
|
private String searchResult;
|
|
}
|
|
}
|