MeshRotation enum

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

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

Поля (1)

МодификаторыТипИмя
NONE, Z_UP_TO_Y_UP, X_UP_TO_Y_UP

Исходный код

Показать/скрыть
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 {
      }
   }
}