PageData class

Пакет: com.hypixel.hytale.builtin.buildertools.objimport

Файл: com/hypixel/hytale/builtin/buildertools/objimport/ObjImportPage.java

Поля (32)

МодификаторыТипИмя
public static final BuilderCodec<ObjImportPage.PageData> CODEC
static final String KEY_AUTO_DETECT_TEXTURES
static final String KEY_BLOCK_PATTERN
static final String KEY_BROWSE
static final String KEY_BROWSER_CANCEL
static final String KEY_BROWSER_SELECT
static final String KEY_FILL_SOLID
static final String KEY_HEIGHT
static final String KEY_IMPORT
static final String KEY_OBJ_PATH
static final String KEY_ORIGIN
static final String KEY_ROTATION
static final String KEY_SCALE
static final String KEY_SIZE_MODE
static final String KEY_USE_MATERIALS
private Boolean autoDetectTextures
private String blockPattern
private Boolean browse
private Boolean browserCancel
private Boolean browserSelect
private Boolean doImport
private String file
private Boolean fillSolid
private Integer height
private String objPath
private String origin
private String rotation
private Float scale
private String searchQuery
private String searchResult
private String sizeMode
private Boolean useMaterials

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.builtin.buildertools.objimport;

class="kw">import com.hypixel.hytale.builtin.buildertools.BlockColorIndex;
class="kw">import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin;
class="kw">import com.hypixel.hytale.builtin.buildertools.utils.PasteToolUtil;
class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.codec.KeyedCodec;
class="kw">import com.hypixel.hytale.codec.builder.BuilderCodec;
class="kw">import com.hypixel.hytale.common.util.PathUtil;
class="kw">import com.hypixel.hytale.common.util.StringUtil;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
class="kw">import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType;
class="kw">import com.hypixel.hytale.protocol.packets.interface_.Page;
class="kw">import com.hypixel.hytale.server.core.Constants;
class="kw">import com.hypixel.hytale.server.core.Message;
class="kw">import com.hypixel.hytale.server.core.asset.AssetModule;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
class="kw">import com.hypixel.hytale.server.core.entity.entities.Player;
class="kw">import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage;
class="kw">import com.hypixel.hytale.server.core.modules.singleplayer.SingleplayerModule;
class="kw">import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection;
class="kw">import com.hypixel.hytale.server.core.ui.DropdownEntryInfo;
class="kw">import com.hypixel.hytale.server.core.ui.LocalizableString;
class="kw">import com.hypixel.hytale.server.core.ui.browser.FileBrowserConfig;
class="kw">import com.hypixel.hytale.server.core.ui.browser.FileBrowserEventData;
class="kw">import com.hypixel.hytale.server.core.ui.browser.ServerFileBrowser;
class="kw">import com.hypixel.hytale.server.core.ui.builder.EventData;
class="kw">import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
class="kw">import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
class="kw">import com.hypixel.hytale.server.core.universe.PlayerRef;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import java.awt.image.BufferedImage;
class="kw">import java.io.IOException;
class="kw">import java.nio.file.Files;
class="kw">import java.nio.file.Path;
class="kw">import java.nio.file.Paths;
class="kw">import java.util.ArrayList;
class="kw">import java.util.HashMap;
class="kw">import java.util.List;
class="kw">import java.util.Locale;
class="kw">import java.util.Map;
class="kw">import java.util.Random;
class="kw">import java.util.Map.Entry;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector3i;

class="kw">public class ObjImportPage class="kw">extends InteractiveCustomUIPage<ObjImportPage.PageData> {
   class="kw">private class="kw">static class="kw">final String DEFAULT_BLOCK = "Rock_Stone";
   class="kw">private class="kw">static class="kw">final int DEFAULT_HEIGHT = 20;
   class="kw">private class="kw">static class="kw">final int MIN_HEIGHT = 1;
   class="kw">private class="kw">static class="kw">final int MAX_HEIGHT = 320;
   class="kw">private class="kw">static class="kw">final float DEFAULT_SCALE = 1.0F;
   class="kw">private class="kw">static class="kw">final float MIN_SCALE = 0.01F;
   class="kw">private class="kw">static class="kw">final float MAX_SCALE = 100.0F;
   class="kw">private class="kw">static class="kw">final String ASSET_PACK_SUB_PATH = "Server/Imports/Models";
   @Nonnull
   class="kw">private String objPath = "";
   class="kw">private int targetHeight = 20;
   class="kw">private boolean useScaleMode = false;
   class="kw">private float scale = 1.0F;
   @Nonnull
   class="kw">private String blockPattern = "Rock_Stone";
   class="kw">private boolean fillSolid = true;
   class="kw">private boolean useMaterials = true;
   class="kw">private boolean autoDetectTextures = false;
   @Nonnull
   class="kw">private String originStr = "bottom_center";
   @Nonnull
   class="kw">private ObjImportPage.Origin origin = ObjImportPage.Origin.BOTTOM_CENTER;
   @Nonnull
   class="kw">private String rotationStr = "y_up";
   @Nonnull
   class="kw">private ObjImportPage.MeshRotation rotation = ObjImportPage.MeshRotation.NONE;
   @Nullable
   class="kw">private Message statusMessage = null;
   class="kw">private boolean isError = false;
   class="kw">private boolean isProcessing = false;
   class="kw">private boolean showBrowser = false;
   @Nonnull
   class="kw">private class="kw">final ServerFileBrowser browser;
   class="kw">private class="kw">static class="kw">final String[] AUTO_DETECT_SUFFIXES = new String[]{"", "_dif", "_diffuse"};
   class="kw">private class="kw">static class="kw">final String[] AUTO_DETECT_EXTENSIONS = new String[]{".png", ".jpg", ".jpeg"};

   class="kw">public ObjImportPage(@Nonnull PlayerRef var1) {
      super(var1, CustomPageLifetime.CanDismiss, ObjImportPage.PageData.CODEC);
      FileBrowserConfig var2 = FileBrowserConfig.builder()
         .listElementId("#BrowserPage #FileList")
         .searchInputId("#BrowserPage #SearchInput")
         .currentPathId("#BrowserPage #CurrentPath")
         .allowedExtensions(".obj")
         .enableRootSelector(false)
         .enableSearch(true)
         .enableDirectoryNav(true)
         .maxResults(50)
         .assetPackMode(true, "Server/Imports/Models")
         .build();
      this.browser = new ServerFileBrowser(var2);
   }

   @Override
   class="kw">public void build(@Nonnull Ref<EntityStore> var1, @Nonnull UICommandBuilder var2, @Nonnull UIEventBuilder var3, @Nonnull Store<EntityStore> var4) {
      var2.append("Pages/ObjImportPage.ui");
      var2.set("#ObjPath #Input.Value", this.objPath);
      var2.set("#HeightInput #Input.Value", this.targetHeight);
      var2.set("#ScaleInput #Input.Value", this.scale);
      var2.set("#BlockPattern #Input.Value", this.blockPattern);
      var2.set("#FillModeCheckbox #CheckBox.Value", this.fillSolid);
      var2.set("#UseMaterialsCheckbox #CheckBox.Value", this.useMaterials);
      var2.set("#AutoDetectTexturesCheckbox #CheckBox.Value", this.autoDetectTextures);
      var2.set("#HeightInput.Visible", !this.useScaleMode);
      var2.set("#ScaleInput.Visible", this.useScaleMode);
      List var5 = new ArrayList<>();
      var5.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.objImport.sizeMode.height"), "height"));
      var5.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.objImport.sizeMode.scale"), "scale"));
      var2.set("#SizeModeInput #Input.Entries", var5);
      var2.set("#SizeModeInput #Input.Value", this.useScaleMode ? "scale" : "height");
      List var6 = new ArrayList<>();
      var6.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.bottom_front_left"), "bottom_front_left"));
      var6.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.bottom_center"), "bottom_center"));
      var6.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.center"), "center"));
      var6.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.origin.top_center"), "top_center"));
      var2.set("#OriginInput #Input.Entries", var6);
      var2.set("#OriginInput #Input.Value", this.originStr);
      List var7 = new ArrayList<>();
      var7.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.objImport.axis.yUp"), "y_up"));
      var7.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.objImport.axis.zUp"), "z_up"));
      var7.add(new DropdownEntryInfo(LocalizableString.fromMessageId("server.customUI.objImport.axis.xUp"), "x_up"));
      var2.set("#RotationInput #Input.Entries", var7);
      var2.set("#RotationInput #Input.Value", this.rotationStr);
      this.updateStatus(var2);
      var3.addEventBinding(CustomUIEventBindingType.ValueChanged, "#ObjPath #Input", EventData.of("@ObjPath", "#ObjPath #Input.Value"), false);
      var3.addEventBinding(CustomUIEventBindingType.ValueChanged, "#HeightInput #Input", EventData.of("@Height", "#HeightInput #Input.Value"), false);
      var3.addEventBinding(CustomUIEventBindingType.ValueChanged, "#ScaleInput #Input", EventData.of("@Scale", "#ScaleInput #Input.Value"), false);
      var3.addEventBinding(CustomUIEventBindingType.ValueChanged, "#SizeModeInput #Input", EventData.of("SizeMode", "#SizeModeInput #Input.Value"), false);
      var3.addEventBinding(CustomUIEventBindingType.ValueChanged, "#BlockPattern #Input", EventData.of("@BlockPattern", "#BlockPattern #Input.Value"), false);
      var3.addEventBinding(
         CustomUIEventBindingType.ValueChanged, "#FillModeCheckbox #CheckBox", EventData.of("@FillSolid", "#FillModeCheckbox #CheckBox.Value"), false
      );
      var3.addEventBinding(
         CustomUIEventBindingType.ValueChanged,
         "#UseMaterialsCheckbox #CheckBox",
         EventData.of("@UseMaterials", "#UseMaterialsCheckbox #CheckBox.Value"),
         false
      );
      var3.addEventBinding(
         CustomUIEventBindingType.ValueChanged,
         "#AutoDetectTexturesCheckbox #CheckBox",
         EventData.of("@AutoDetectTextures", "#AutoDetectTexturesCheckbox #CheckBox.Value"),
         false
      );
      var3.addEventBinding(CustomUIEventBindingType.ValueChanged, "#OriginInput #Input", EventData.of("@Origin", "#OriginInput #Input.Value"), false);
      var3.addEventBinding(CustomUIEventBindingType.ValueChanged, "#RotationInput #Input", EventData.of("@Rotation", "#RotationInput #Input.Value"), false);
      var3.addEventBinding(CustomUIEventBindingType.Activating, "#ImportButton", EventData.of("Import", "true"));
      var3.addEventBinding(CustomUIEventBindingType.Activating, "#ObjPath #BrowseButton", EventData.of("Browse", "true"));
      var2.set("#FormContainer.Visible", !this.showBrowser);
      var2.set("#BrowserPage.Visible", this.showBrowser);
      if (this.showBrowser) {
         this.buildBrowserPage(var2, var3);
      }
   }

   class="kw">private void buildBrowserPage(@Nonnull UICommandBuilder var1, @Nonnull UIEventBuilder var2) {
      this.browser.buildSearchInput(var1, var2);
      this.browser.buildCurrentPath(var1);
      this.browser.buildFileList(var1, var2);
      var2.addEventBinding(CustomUIEventBindingType.Activating, "#BrowserPage #SelectButton", EventData.of("BrowserSelect", "true"));
      var2.addEventBinding(CustomUIEventBindingType.Activating, "#BrowserPage #CancelButton", EventData.of("BrowserCancel", "true"));
   }

   class="kw">private void updateStatus(@Nonnull UICommandBuilder var1) {
      if (this.statusMessage != null) {
         var1.set("#StatusText.Text", this.statusMessage);
         var1.set("#StatusText.Visible", true);
         var1.set("#StatusText.Style.TextColor", this.isError ? "#e74c3c" : "#cfd8e3");
      } else {
         var1.set("#StatusText.Visible", false);
      }
   }

   class="kw">private void setError(@Nonnull Message var1) {
      this.statusMessage = var1;
      this.isError = true;
      this.isProcessing = false;
      this.rebuild();
   }

   class="kw">private void setStatus(@Nonnull Message var1) {
      this.statusMessage = var1;
      this.isError = false;
      this.rebuild();
   }

   class="kw">public void handleDataEvent(@Nonnull Ref<EntityStore> var1, @Nonnull Store<EntityStore> var2, @Nonnull ObjImportPage.PageData var3) {
      if (var3.browse != null && var3.browse) {
         this.showBrowser = true;
         this.rebuild();
      } else if (var3.browserCancel != null && var3.browserCancel) {
         this.showBrowser = false;
         this.rebuild();
      } else if (var3.browserSelect != null && var3.browserSelect) {
         this.showBrowser = false;
         this.rebuild();
      } else if (!this.showBrowser || !this.handleBrowserEvent(var3)) {
         boolean var4 = false;
         if (var3.objPath != null) {
            this.objPath = StringUtil.stripQuotes(var3.objPath.trim());
            this.statusMessage = null;
            var4 = true;
         }

         if (var3.height != null) {
            this.targetHeight = Math.max(1, Math.min(320, var3.height));
            var4 = true;
         }

         if (var3.scale != null) {
            this.scale = Math.max(0.01F, Math.min(100.0F, var3.scale));
            var4 = true;
         }

         if (var3.sizeMode != null) {
            this.useScaleMode = "scale".equalsIgnoreCase(var3.sizeMode);
            this.rebuild();
         } else {
            if (var3.blockPattern != null) {
               this.blockPattern = var3.blockPattern.trim();
               var4 = true;
            }

            if (var3.fillSolid != null) {
               this.fillSolid = var3.fillSolid;
               var4 = true;
            }

            if (var3.useMaterials != null) {
               this.useMaterials = var3.useMaterials;
               var4 = true;
            }

            if (var3.autoDetectTextures != null) {
               this.autoDetectTextures = var3.autoDetectTextures;
               var4 = true;
            }

            if (var3.origin != null) {
               this.originStr = var3.origin.trim().toLowerCase(Locale.ROOT);

               this.origin = class="kw">switch (this.originStr) {
                  case "bottom_front_left" -> ObjImportPage.Origin.BOTTOM_FRONT_LEFT;
                  case "center" -> ObjImportPage.Origin.CENTER;
                  case "top_center" -> ObjImportPage.Origin.TOP_CENTER;
                  class="kw">default -> ObjImportPage.Origin.BOTTOM_CENTER;
               };
               var4 = true;
            }

            if (var3.rotation != null) {
               this.rotationStr = var3.rotation.trim().toLowerCase(Locale.ROOT);

               this.rotation = class="kw">switch (this.rotationStr) {
                  case "z_up" -> ObjImportPage.MeshRotation.Z_UP_TO_Y_UP;
                  case "x_up" -> ObjImportPage.MeshRotation.X_UP_TO_Y_UP;
                  class="kw">default -> ObjImportPage.MeshRotation.NONE;
               };
               var4 = true;
            }

            if (var3.doImport != null && var3.doImport && !this.isProcessing) {
               this.performImport(var1, var2);
            } else {
               if (var4) {
                  this.sendUpdate();
               }
            }
         }
      }
   }

   class="kw">private boolean handleBrowserEvent(@Nonnull ObjImportPage.PageData var1) {
      if (var1.searchQuery != null) {
         this.browser.setSearchQuery(var1.searchQuery.trim().toLowerCase(Locale.ROOT));
         this.rebuildBrowser();
         class="kw">return true;
      }

      if (var1.file != null) {
         String var2 = var1.file;
         if ("..".equals(var2)) {
            this.browser.navigateUp();
            this.rebuildBrowser();
            class="kw">return true;
         }

         if (this.browser.handleEvent(FileBrowserEventData.file(var2))) {
            this.rebuildBrowser();
            class="kw">return true;
         }

         String var3 = this.browser.getAssetPackCurrentPath().isEmpty() ? var2 : this.browser.getAssetPackCurrentPath() + "/" + var2;
         Path var4 = this.browser.resolveAssetPackPath(var3);
         if (var4 != null && Files.isRegularFile(var4)) {
            this.objPath = var4.toString();
            this.showBrowser = false;
            this.rebuild();
            class="kw">return true;
         }
      }

      if (var1.searchResult != null) {
         Path var5 = this.browser.resolveAssetPackPath(var1.searchResult);
         if (var5 != null && Files.isRegularFile(var5)) {
            this.objPath = var5.toString();
            this.showBrowser = false;
            this.rebuild();
            class="kw">return true;
         }
      }

      class="kw">return false;
   }

   class="kw">private void rebuildBrowser() {
      UICommandBuilder var1 = new UICommandBuilder();
      UIEventBuilder var2 = new UIEventBuilder();
      this.browser.buildFileList(var1, var2);
      this.browser.buildCurrentPath(var1);
      this.sendUpdate(var1, var2, false);
   }

   @Nullable
   class="kw">private List<ObjImportPage.WeightedBlock> parseBlockPattern(@Nonnull String var1) {
      List var2 = new ArrayList<>();
      String[] var3 = var1.split(",", 0);

      for (String var7 : var3) {
         var7 = var7.trim();
         if (!var7.isEmpty()) {
            int var8 = 100;
            String var9 = var7;
            int var10 = var7.indexOf(37);
            if (var10 > 0) {
               try {
                  var8 = Integer.parseInt(var7.substring(0, var10).trim());
                  var9 = var7.substring(var10 + 1).trim();
               } catch (NumberFormatException var12) {
                  class="kw">return null;
               }
            }

            int var11 = BlockType.getAssetMap().getIndex(var9);
            if (var11 == Integer.MIN_VALUE) {
               class="kw">return null;
            }

            var2.add(new ObjImportPage.WeightedBlock(var11, var8));
         }
      }

      class="kw">return var2.isEmpty() ? null : var2;
   }

   class="kw">private int selectRandomBlock(@Nonnull List<ObjImportPage.WeightedBlock> var1, @Nonnull Random var2) {
      if (var1.isEmpty()) {
         throw new IllegalStateException("Cannot select from empty blocks list");
      }

      if (var1.size() == 1) {
         class="kw">return var1.getFirst().blockId;
      }

      int var3 = 0;

      for (ObjImportPage.WeightedBlock var5 : var1) {
         var3 += var5.weight;
      }

      if (var3 <= 0) {
         class="kw">return var1.getFirst().blockId;
      }

      int var8 = var2.nextInt(var3);
      int var9 = 0;

      for (ObjImportPage.WeightedBlock var7 : var1) {
         var9 += var7.weight;
         if (var8 < var9) {
            class="kw">return var7.blockId;
         }
      }

      class="kw">return var1.getFirst().blockId;
   }

   class="kw">private void performImport(@Nonnull Ref<EntityStore> var1, @Nonnull Store<EntityStore> var2) {
      if (this.objPath.isEmpty()) {
         this.setError(Message.translation("server.builderTools.objImport.emptyPath"));
      } else if (!this.objPath.toLowerCase(Locale.ROOT).endsWith(".obj")) {
         this.setError(Message.translation("server.builderTools.objImport.invalidExtension"));
      } else {
         Path var3 = Paths.get(this.objPath);
         boolean var4 = Constants.SINGLEPLAYER && SingleplayerModule.isOwner(this.playerRef);
         if (!var4 && !AssetModule.get().isWithinPackSubDir(var3, "Server/Imports/Models")) {
            this.setError(Message.translation("server.builderTools.objImport.notInImportsDir"));
         } else if (!Files.exists(var3)) {
            this.setError(Message.translation("server.builderTools.objImport.fileNotFound").param("path", this.objPath));
         } else {
            List var5 = this.parseBlockPattern(this.blockPattern);
            if (var5 == null) {
               this.setError(Message.translation("server.builderTools.objImport.invalidPattern").param("pattern", this.blockPattern));
            } else {
               this.isProcessing = true;
               this.setStatus(Message.translation("server.builderTools.objImport.processing"));
               Player var6 = var2.getComponent(var1, Player.getComponentType());
               PlayerRef var7 = var2.getComponent(var1, PlayerRef.getComponentType());
               if (var6 != null && var7 != null) {
                  int var8 = this.targetHeight;
                  boolean var9 = this.useScaleMode;
                  float var10 = this.scale;
                  String var11 = this.objPath;
                  boolean var12 = this.fillSolid;
                  boolean var13 = this.useMaterials;
                  boolean var14 = this.autoDetectTextures;
                  ObjImportPage.Origin var15 = this.origin;
                  ObjImportPage.MeshRotation var16 = this.rotation;
                  List var17 = var5;
                  BuilderToolsPlugin.addToQueue(
                     var6,
                     var7,
                     (var14x, var15x, var16x) -> {
                        try {
                           Path var17 = Paths.get(var11);
                           ObjParser.ObjMesh var18 = ObjParser.parse(var17);
                           class="kw">switch (var16) {
                              case Z_UP_TO_Y_UP:
                                 var18.transformZUpToYUp();
                                 break;
                              case X_UP_TO_Y_UP:
                                 var18.transformXUpToYUp();
                           }

                           int var19;
                           if (var9) {
                              float[] var20 = var18.getBounds();
                              float var21 = var20[4] - var20[1];
                              var19 = Math.max(1, (int)Math.ceil(var21 * var10));
                           } else {
                              var19 = var8;
                           }

                           if (var17.isEmpty()) {
                              this.setError(Message.translation("server.builderTools.objImport.noBlocks"));
                              class="kw">return;
                           }

                           BlockColorIndex var40 = BuilderToolsPlugin.get().getBlockColorIndex();
                           Map var41 = new HashMap<>();
                           Map var22 = new HashMap<>();
                           int var23 = var17.getFirst().blockId;
                           if (var13 && var18.mtlLib() != null) {
                              this.loadMaterialData(var17, var18, var40, var41, var22, var14);
                              if (!var22.isEmpty()) {
                                 var23 = var22.values().iterator().next();
                              }
                           }

                           boolean var24 = var18.hasUvCoordinates() && !var41.isEmpty();
                           boolean var25 = var15 == ObjImportPage.Origin.BOTTOM_FRONT_LEFT;
                           MeshVoxelizer.VoxelResult var26;
                           if (var24) {
                              var26 = MeshVoxelizer.voxelize(var18, var19, var12, var41, var22, var40, var23, var25);
                           } else {
                              var26 = MeshVoxelizer.voxelize(var18, var19, var12, null, var22, var40, var23, var25);
                           }

                           TextureSampler.clearCache();
                           int var27 = 0;
                           int var28 = 0;
                           int var29 = 0;
                           class="kw">switch (var15) {
                              case BOTTOM_FRONT_LEFT:
                              class="kw">default:
                                 break;
                              case BOTTOM_CENTER:
                                 var27 = -var26.sizeX() / 2;
                                 var29 = -var26.sizeZ() / 2;
                                 break;
                              case CENTER:
                                 var27 = -var26.sizeX() / 2;
                                 var28 = -var26.sizeY() / 2;
                                 var29 = -var26.sizeZ() / 2;
                                 break;
                              case TOP_CENTER:
                                 var27 = -var26.sizeX() / 2;
                                 var28 = -var26.sizeY();
                                 var29 = -var26.sizeZ() / 2;
                           }

                           BlockSelection var30 = new BlockSelection(var26.countSolid(), 0);
                           var30.setPosition(0, 0, 0);
                           Random var31 = new Random();
                           boolean var32 = var26.blockIds() != null;

                           for (int var33 = 0; var33 < var26.sizeX(); var33++) {
                              for (int var34 = 0; var34 < var26.sizeY(); var34++) {
                                 for (int var35 = 0; var35 < var26.sizeZ(); var35++) {
                                    if (var26.voxels()[var33][var34][var35]) {
                                       int var36;
                                       if (var32) {
                                          var36 = var26.getBlockId(var33, var34, var35);
                                          if (var36 == 0) {
                                             var36 = this.selectRandomBlock(var17, var31);
                                          }
                                       } else {
                                          var36 = this.selectRandomBlock(var17, var31);
                                       }

                                       var30.addBlockAtLocalPos(var33 + var27, var34 + var28, var35 + var29, var36, 0, 0, 0);
                                    }
                                 }
                              }
                           }

                           var30.setSelectionArea(
                              new Vector3i(var27, var28, var29), new Vector3i(var26.sizeX() - 1 + var27, var26.sizeY() - 1 + var28, var26.sizeZ() - 1 + var29)
                           );
                           var15x.setSelection(var30);
                           var15x.sendSelectionToClient();
                           int var42 = var26.countSolid();
                           this.statusMessage = Message.translation("server.builderTools.objImport.success")
                              .param("count", var42)
                              .param("width", var26.sizeX())
                              .param("height", var26.sizeY())
                              .param("depth", var26.sizeZ());
                           this.isProcessing = false;
                           var7.sendMessage(
                              Message.translation("server.builderTools.objImport.success")
                                 .param("count", var42)
                                 .param("width", var26.sizeX())
                                 .param("height", var26.sizeY())
                                 .param("depth", var26.sizeZ())
                           );
                           var6.getPageManager().setPage(var14x, var2, Page.None);
                           PasteToolUtil.switchToPasteTool(var14x, var7, var16x);
                        } catch (ObjParser.ObjParseException var37) {
                           BuilderToolsPlugin.get().getLogger().at(Level.WARNING).log("OBJ parse error: %s", var37.getMessage());
                           this.setError(Message.translation("server.builderTools.objImport.parseError").param("message", var37.getMessage()));
                        } catch (IOException var38) {
                           ((HytaleLogger.Api)BuilderToolsPlugin.get().getLogger().at(Level.WARNING).withCause(var38)).log("OBJ class="kw">import IO error");
                           this.setError(Message.translation("server.builderTools.objImport.ioError").param("message", var38.getMessage()));
                        } catch (Exception var39) {
                           ((HytaleLogger.Api)BuilderToolsPlugin.get().getLogger().at(Level.WARNING).withCause(var39)).log("OBJ class="kw">import error");
                           this.setError(Message.translation("server.builderTools.objImport.error").param("message", var39.getMessage()));
                        }
                     }
                  );
               } else {
                  this.setError(Message.translation("server.builderTools.objImport.playerNotFound"));
               }
            }
         }
      }
   }

   class="kw">private void loadMaterialData(
      @Nonnull Path var1,
      @Nonnull ObjParser.ObjMesh var2,
      @Nonnull BlockColorIndex var3,
      @Nonnull Map<String, BufferedImage> var4,
      @Nonnull Map<String, Integer> var5,
      boolean var6
   ) class="kw">throws IOException {
      if (var2.mtlLib() != null) {
         Path var7 = PathUtil.resolvePathWithinDir(var1.getParent(), var2.mtlLib());
         if (var7 != null && Files.exists(var7)) {
            Map var8 = MtlParser.parse(var7);
            Path var9 = var7.getParent();

            for (Entry var11 : var8.entrySet()) {
               String var12 = var11.getKey();
               MtlParser.MtlMaterial var13 = var11.getValue();
               String var14 = var13.diffuseTexturePath();
               if (var14 == null && var6) {
                  var14 = findMatchingTexture(var9, var12);
               }

               if (var14 != null) {
                  Path var15 = PathUtil.resolvePathWithinDir(var9, var14);
                  if (var15 == null) {
                     class="kw">continue;
                  }

                  BufferedImage var16 = TextureSampler.loadTexture(var15);
                  if (var16 != null) {
                     var4.put(var12, var16);
                     int[] var17 = TextureSampler.getAverageColor(var15);
                     if (var17 != null) {
                        int var18 = var3.findClosestBlock(var17[0], var17[1], var17[2]);
                        if (var18 > 0) {
                           var5.put(var12, var18);
                        }
                     }
                     class="kw">continue;
                  }
               }

               int[] var19 = var13.getDiffuseColorRGB();
               if (var19 != null) {
                  int var20 = var3.findClosestBlock(var19[0], var19[1], var19[2]);
                  if (var20 > 0) {
                     var5.put(var12, var20);
                  }
               }
            }
         }
      }
   }

   @Nullable
   class="kw">private class="kw">static String findMatchingTexture(@Nonnull Path var0, @Nonnull String var1) {
      for (String var5 : AUTO_DETECT_SUFFIXES) {
         for (String var9 : AUTO_DETECT_EXTENSIONS) {
            String var10 = var1 + var5 + var9;
            if (Files.exists(var0.resolve(var10))) {
               class="kw">return var10;
            }
         }
      }

      class="kw">return null;
   }

   class="kw">public enum MeshRotation {
      NONE,
      Z_UP_TO_Y_UP,
      X_UP_TO_Y_UP;

      MeshRotation() {
      }
   }

   class="kw">public enum Origin {
      BOTTOM_FRONT_LEFT,
      BOTTOM_CENTER,
      CENTER,
      TOP_CENTER;

      Origin() {
      }
   }

   class="kw">public class="kw">static class PageData {
      class="kw">static class="kw">final String KEY_OBJ_PATH = "@ObjPath";
      class="kw">static class="kw">final String KEY_HEIGHT = "@Height";
      class="kw">static class="kw">final String KEY_SCALE = "@Scale";
      class="kw">static class="kw">final String KEY_SIZE_MODE = "SizeMode";
      class="kw">static class="kw">final String KEY_BLOCK_PATTERN = "@BlockPattern";
      class="kw">static class="kw">final String KEY_FILL_SOLID = "@FillSolid";
      class="kw">static class="kw">final String KEY_USE_MATERIALS = "@UseMaterials";
      class="kw">static class="kw">final String KEY_AUTO_DETECT_TEXTURES = "@AutoDetectTextures";
      class="kw">static class="kw">final String KEY_ORIGIN = "@Origin";
      class="kw">static class="kw">final String KEY_ROTATION = "@Rotation";
      class="kw">static class="kw">final String KEY_IMPORT = "Import";
      class="kw">static class="kw">final String KEY_BROWSE = "Browse";
      class="kw">static class="kw">final String KEY_BROWSER_SELECT = "BrowserSelect";
      class="kw">static class="kw">final String KEY_BROWSER_CANCEL = "BrowserCancel";
      class="kw">public class="kw">static class="kw">final BuilderCodec<ObjImportPage.PageData> CODEC = BuilderCodec.builder(ObjImportPage.PageData.class, ObjImportPage.PageData::new)
         .append(new KeyedCodec<>("@ObjPath", Codec.STRING), (var0, var1) -> var0.objPath = var1, var0 -> var0.objPath)
         .add()
         .append(new KeyedCodec<>("@Height", Codec.INTEGER), (var0, var1) -> var0.height = var1, var0 -> var0.height)
         .add()
         .append(new KeyedCodec<>("@Scale", Codec.FLOAT), (var0, var1) -> var0.scale = var1, var0 -> var0.scale)
         .add()
         .append(new KeyedCodec<>("SizeMode", Codec.STRING), (var0, var1) -> var0.sizeMode = var1, var0 -> var0.sizeMode)
         .add()
         .append(new KeyedCodec<>("@BlockPattern", Codec.STRING), (var0, var1) -> var0.blockPattern = var1, var0 -> var0.blockPattern)
         .add()
         .append(new KeyedCodec<>("@FillSolid", Codec.BOOLEAN), (var0, var1) -> var0.fillSolid = var1, var0 -> var0.fillSolid)
         .add()
         .append(new KeyedCodec<>("@UseMaterials", Codec.BOOLEAN), (var0, var1) -> var0.useMaterials = var1, var0 -> var0.useMaterials)
         .add()
         .append(new KeyedCodec<>("@AutoDetectTextures", Codec.BOOLEAN), (var0, var1) -> var0.autoDetectTextures = var1, var0 -> var0.autoDetectTextures)
         .add()
         .append(new KeyedCodec<>("@Origin", Codec.STRING), (var0, var1) -> var0.origin = var1, var0 -> var0.origin)
         .add()
         .append(new KeyedCodec<>("@Rotation", Codec.STRING), (var0, var1) -> var0.rotation = var1, var0 -> var0.rotation)
         .add()
         .append(
            new KeyedCodec<>("Import", Codec.STRING),
            (var0, var1) -> var0.doImport = "true".equalsIgnoreCase(var1),
            var0 -> var0.doImport != null && var0.doImport ? "true" : null
         )
         .add()
         .append(
            new KeyedCodec<>("Browse", Codec.STRING),
            (var0, var1) -> var0.browse = "true".equalsIgnoreCase(var1),
            var0 -> var0.browse != null && var0.browse ? "true" : null
         )
         .add()
         .append(
            new KeyedCodec<>("BrowserSelect", Codec.STRING),
            (var0, var1) -> var0.browserSelect = "true".equalsIgnoreCase(var1),
            var0 -> var0.browserSelect != null && var0.browserSelect ? "true" : null
         )
         .add()
         .append(
            new KeyedCodec<>("BrowserCancel", Codec.STRING),
            (var0, var1) -> var0.browserCancel = "true".equalsIgnoreCase(var1),
            var0 -> var0.browserCancel != null && var0.browserCancel ? "true" : null
         )
         .add()
         .append(new KeyedCodec<>("File", Codec.STRING), (var0, var1) -> var0.file = var1, var0 -> var0.file)
         .add()
         .append(new KeyedCodec<>("@SearchQuery", Codec.STRING), (var0, var1) -> var0.searchQuery = var1, var0 -> var0.searchQuery)
         .add()
         .append(new KeyedCodec<>("SearchResult", Codec.STRING), (var0, var1) -> var0.searchResult = var1, var0 -> var0.searchResult)
         .add()
         .build();
      @Nullable
      class="kw">private String objPath;
      @Nullable
      class="kw">private Integer height;
      @Nullable
      class="kw">private Float scale;
      @Nullable
      class="kw">private String sizeMode;
      @Nullable
      class="kw">private String blockPattern;
      @Nullable
      class="kw">private Boolean fillSolid;
      @Nullable
      class="kw">private Boolean useMaterials;
      @Nullable
      class="kw">private Boolean autoDetectTextures;
      @Nullable
      class="kw">private String origin;
      @Nullable
      class="kw">private String rotation;
      @Nullable
      class="kw">private Boolean doImport;
      @Nullable
      class="kw">private Boolean browse;
      @Nullable
      class="kw">private Boolean browserSelect;
      @Nullable
      class="kw">private Boolean browserCancel;
      @Nullable
      class="kw">private String file;
      @Nullable
      class="kw">private String searchQuery;
      @Nullable
      class="kw">private String searchResult;

      class="kw">public PageData() {
      }
   }

   class="kw">private record WeightedBlock(int blockId, int weight) {
      class="kw">private WeightedBlock {
      }
   }
}