diff --git a/common/src/main/java/xaeroplus/XaeroPlus.java b/common/src/main/java/xaeroplus/XaeroPlus.java index dde1fffe..9411aa3e 100644 --- a/common/src/main/java/xaeroplus/XaeroPlus.java +++ b/common/src/main/java/xaeroplus/XaeroPlus.java @@ -2,6 +2,7 @@ import net.lenni0451.lambdaevents.LambdaManager; import net.lenni0451.lambdaevents.generator.LambdaMetaFactoryGenerator; +import net.minecraft.DetectedVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import xaero.map.platform.Services; @@ -19,6 +20,8 @@ public class XaeroPlus { public static final LambdaManager EVENT_BUS = LambdaManager.basic(new LambdaMetaFactoryGenerator()); public static final AtomicBoolean initialized = new AtomicBoolean(false); public static final File configFile = Services.PLATFORM.getConfigDir().resolve("xaeroplus.txt").toFile(); + public static String XP_VERSION = "2"; + public static final String MC_VERSION = DetectedVersion.BUILT_IN.getName(); public static void initializeSettings() { loadXPSettings(); diff --git a/common/src/main/java/xaeroplus/mixin/client/MixinGuiWaypoints.java b/common/src/main/java/xaeroplus/mixin/client/MixinGuiWaypoints.java index c30a3d96..2e2df842 100644 --- a/common/src/main/java/xaeroplus/mixin/client/MixinGuiWaypoints.java +++ b/common/src/main/java/xaeroplus/mixin/client/MixinGuiWaypoints.java @@ -106,7 +106,7 @@ public boolean charTyped(char c, int i) { @Inject(method = "render", at = @At(value = "INVOKE", target = "Lxaero/common/gui/ScreenBase;render(Lnet/minecraft/client/gui/GuiGraphics;IIF)V", shift = At.Shift.AFTER), remap = true) public void drawScreenInject(final GuiGraphics guiGraphics, final int mouseX, final int mouseY, final float partial, final CallbackInfo ci) { if (!this.searchField.isFocused() && this.searchField.getValue().isEmpty()) { - xaero.map.misc.Misc.setFieldText(this.searchField, I18n.get("xaeroplus.gui.xaero_settings_search_placeholder", new Object[0]), -11184811); + xaero.map.misc.Misc.setFieldText(this.searchField, I18n.get("gui.xaero_settings_search_placeholder", new Object[0]), -11184811); this.searchField.moveCursorToStart(false); } this.searchField.render(guiGraphics, mouseX, mouseY, partial); diff --git a/common/src/main/java/xaeroplus/util/AtlasWaypointImport.java b/common/src/main/java/xaeroplus/util/AtlasWaypointImport.java new file mode 100644 index 00000000..f83e7f3d --- /dev/null +++ b/common/src/main/java/xaeroplus/util/AtlasWaypointImport.java @@ -0,0 +1,148 @@ +package xaeroplus.util; + +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; +import xaero.common.minimap.waypoints.Waypoint; +import xaero.hud.minimap.BuiltInHudModules; +import xaero.hud.minimap.module.MinimapSession; +import xaero.hud.minimap.waypoint.WaypointColor; +import xaero.hud.minimap.waypoint.WaypointPurpose; +import xaero.hud.minimap.waypoint.set.WaypointSet; +import xaero.hud.minimap.world.MinimapWorld; +import xaero.hud.path.XaeroPath; +import xaero.map.mods.SupportMods; +import xaeroplus.XaeroPlus; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.*; +import java.util.stream.Collectors; + +public final class AtlasWaypointImport { + private AtlasWaypointImport() {} + + public static int importAtlasWaypoints() { + MinimapSession minimapSession = BuiltInHudModules.MINIMAP.getCurrentSession(); + if (minimapSession == null) return 0; + MinimapWorld currentWorld = minimapSession.getWorldManager().getCurrentWorld(); + if (currentWorld == null) return 0; + WaypointSet currentWpSet = currentWorld.getCurrentWaypointSet(); + if (currentWpSet == null) return 0; + + List atlasWaypoints = getAtlasApiResponse(); + if (atlasWaypoints.isEmpty()) return 0; + Map, ArrayList> atlasByDimension = atlasWaypoints.stream() + .filter(AtlasWaypoint::isValid) + .collect(Collectors.toMap( + k -> Objects.equals(0, k.end_dimension) + ? Level.OVERWORLD + : Level.END, + v -> { + var l = new ArrayList(); + l.add(v); + return l; + }, + (v1, v2) -> { + v1.addAll(v2); + return v1; + } + )); + ResourceKey currentWaypointWorldDim = currentWorld.getDimId(); + ResourceKey altDim = Objects.equals(currentWaypointWorldDim, Level.OVERWORLD) + ? Level.END + : Level.OVERWORLD; + var rootContainer = minimapSession.getWorldManager().getCurrentRootContainer(); + MinimapWorld altWorld = null; + for (MinimapWorld world : rootContainer.getWorlds()) { + if (world.getDimId() == altDim) { + altWorld = world; + } + } + if (altWorld == null) { + String waystoneDimensionDirectoryName = minimapSession.getDimensionHelper().getDimensionDirectoryName(altDim); + String waystoneWpWorldNode = minimapSession.getWorldStateUpdater().getPotentialWorldNode(altDim, true); + XaeroPath waystoneWpContainerPath = minimapSession.getWorldState() + .getAutoRootContainerPath() + .resolve(waystoneDimensionDirectoryName) + .resolve(waystoneWpWorldNode); + altWorld = minimapSession.getWorldManager().getWorld(waystoneWpContainerPath); + } + if (currentWorld.getWaypointSet("atlas") != null) { + currentWorld.getWaypointSet("atlas").clear(); + } + if (altWorld.getWaypointSet("atlas") != null) { + altWorld.getWaypointSet("atlas").clear(); + } + int addedWaypoints = 0; + for (var atlasWp : atlasByDimension.entrySet()) { + ResourceKey dim = atlasWp.getKey(); + List waypoints = atlasWp.getValue(); + MinimapWorld world = Objects.equals(dim, currentWorld.getDimId()) + ? currentWorld + : altWorld; + WaypointSet waypointSet = world.getWaypointSet("atlas"); + if (waypointSet == null) { + world.addWaypointSet("atlas"); + waypointSet = world.getWaypointSet("atlas"); + } + for (var waypoint : waypoints) { + Waypoint wp = new Waypoint( + waypoint.x, + waypoint.y == null ? 64 : waypoint.y, + waypoint.z, + waypoint.name, + waypoint.name.substring(0, Math.min(2, waypoint.name.length())), + WaypointColor.getRandom(), + WaypointPurpose.NORMAL + ); + waypointSet.add(wp); + addedWaypoints++; + } + } + SupportMods.xaeroMinimap.requestWaypointsRefresh(); + return addedWaypoints; + } + + private static List getAtlasApiResponse() { + HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .connectTimeout(Duration.ofSeconds(2)) + .build(); + try { + HttpRequest req = HttpRequest.newBuilder() + .uri(URI.create("https://2b2tAtlas.com/api/locations.php")) + .headers("User-Agent", "XaeroPlus/" + XaeroPlus.XP_VERSION + "+" + XaeroPlus.MC_VERSION) + .timeout(Duration.ofSeconds(10)) + .GET() + .build(); + var response = client.send(req, HttpResponse.BodyHandlers.ofString()); + var gson = new GsonBuilder() + .disableHtmlEscaping() + .setLenient() + .create(); + return gson.fromJson(response.body(), new TypeToken>() {}); + } catch (final Exception e) { + XaeroPlus.LOGGER.error("Failed to get Atlas API response", e); + return Collections.emptyList(); + } + } + + + public static class AtlasWaypoint { + public String name; + public Integer x; + @Nullable public Integer y; + public Integer z; + public Integer end_dimension; + + public boolean isValid() { + return name != null && x != null && z != null && end_dimension != null; + } + } +} diff --git a/fabric/src/main/java/xaeroplus/fabric/XaeroPlusFabric.java b/fabric/src/main/java/xaeroplus/fabric/XaeroPlusFabric.java index f0f83459..6b1a48ac 100644 --- a/fabric/src/main/java/xaeroplus/fabric/XaeroPlusFabric.java +++ b/fabric/src/main/java/xaeroplus/fabric/XaeroPlusFabric.java @@ -6,8 +6,12 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.Version; +import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; import net.minecraft.server.packs.PackType; import xaeroplus.XaeroPlus; import xaeroplus.fabric.util.FabricWaystonesHelperInit; @@ -15,9 +19,12 @@ import xaeroplus.fabric.util.compat.IncompatibleMinimapWarningScreen; import xaeroplus.fabric.util.compat.XaeroPlusMinimapCompatibilityChecker; import xaeroplus.settings.Settings; +import xaeroplus.util.AtlasWaypointImport; import xaeroplus.util.DataFolderResolveUtil; import xaeroplus.util.XaeroPlusGameTest; +import java.util.concurrent.CompletableFuture; + import static xaeroplus.fabric.util.compat.XaeroPlusMinimapCompatibilityChecker.versionCheckResult; public class XaeroPlusFabric implements ClientModInitializer { @@ -30,6 +37,11 @@ public static void initialize() { versionCheckResult.anyPresentMinimapVersion().map(Version::getFriendlyString).orElse("None!")); return; } + XaeroPlus.XP_VERSION = FabricLoader.getInstance().getModContainer("xaeroplus") + .map(ModContainer::getMetadata) + .map(ModMetadata::getVersion) + .map(Version::getFriendlyString) + .orElse("2.x"); FabricWaystonesHelperInit.doInit(); XaeroPlus.initializeSettings(); Settings.REGISTRY.getKeybindings().forEach(KeyBindingHelper::registerKeyBinding); @@ -58,6 +70,20 @@ public void onInitializeClient() { c.getSource().sendFeedback(DataFolderResolveUtil.getCurrentWaypointDataDirPath()); return 1; })); + dispatcher.register(ClientCommandManager.literal("xaero2b2tAtlasImport").executes(c -> { + c.getSource().sendFeedback(Component.literal("Atlas import started...")); + CompletableFuture.runAsync(() -> { + try { + int addedCount = AtlasWaypointImport.importAtlasWaypoints(); + c.getSource().sendFeedback(Component.literal(addedCount + " waypoints imported to the \"atlas\" waypoint set!")); + } catch (final Exception e) { + XaeroPlus.LOGGER.error("Atlas import failed", e); + c.getSource().sendFeedback(Component.literal("Atlas import failed! Check log for details.")); + } + }).whenCompleteAsync((a, b) -> c.getSource() + .sendFeedback(Component.literal("Atlas Import Complete!"))); + return 1; + })); }); ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(new XPShaderResourceReloadListener()); } diff --git a/forge/src/main/java/xaeroplus/forge/XaeroPlusForge.java b/forge/src/main/java/xaeroplus/forge/XaeroPlusForge.java index 420ba3b1..56763ce2 100644 --- a/forge/src/main/java/xaeroplus/forge/XaeroPlusForge.java +++ b/forge/src/main/java/xaeroplus/forge/XaeroPlusForge.java @@ -15,6 +15,7 @@ import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.loading.FMLLoader; import xaero.map.gui.GuiWorldMapSettings; import xaeroplus.XaeroPlus; import xaeroplus.feature.extensions.GuiXaeroPlusWorldMapSettings; @@ -51,6 +52,7 @@ public void onInitialize(FMLClientSetupEvent event) { public void onRegisterKeyMappingsEvent(final RegisterKeyMappingsEvent event) { if (XaeroPlus.initialized.compareAndSet(false, true)) { + XaeroPlus.XP_VERSION = FMLLoader.getLoadingModList().getModFileById("xaeroplus").versionString(); XaeroPlus.initializeSettings(); Settings.REGISTRY.getKeybindings().forEach(event::register); if (System.getenv("XP_CI_TEST") != null) diff --git a/neo/src/main/java/xaeroplus/neo/XaeroPlusNeo.java b/neo/src/main/java/xaeroplus/neo/XaeroPlusNeo.java index 75ef80e7..0b524000 100644 --- a/neo/src/main/java/xaeroplus/neo/XaeroPlusNeo.java +++ b/neo/src/main/java/xaeroplus/neo/XaeroPlusNeo.java @@ -10,20 +10,17 @@ import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.fml.loading.FMLLoader; import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; import net.neoforged.neoforge.common.NeoForge; -import xaero.map.gui.GuiWorldMapSettings; import xaeroplus.XaeroPlus; -import xaeroplus.feature.extensions.GuiXaeroPlusWorldMapSettings; import xaeroplus.settings.Settings; import xaeroplus.util.DataFolderResolveUtil; import xaeroplus.util.XaeroPlusGameTest; -import java.util.List; - @Mod(value = "xaeroplus", dist = Dist.CLIENT) public class XaeroPlusNeo { public static final IEventBus FORGE_EVENT_BUS = NeoForge.EVENT_BUS; @@ -50,6 +47,7 @@ public void onInitialize(FMLClientSetupEvent event) { public void onRegisterKeyMappingsEvent(final RegisterKeyMappingsEvent event) { if (XaeroPlus.initialized.compareAndSet(false, true)) { + XaeroPlus.XP_VERSION = FMLLoader.getLoadingModList().getModFileById("xaeroplus").versionString(); XaeroPlus.initializeSettings(); Settings.REGISTRY.getKeybindings().forEach(event::register); if (System.getenv("XP_CI_TEST") != null)