diff --git a/src/main/java/net/kyrptonaught/serverutils/customMapLoader/CustomMapLoaderMod.java b/src/main/java/net/kyrptonaught/serverutils/customMapLoader/CustomMapLoaderMod.java index 9ccb7c4..5f7b095 100644 --- a/src/main/java/net/kyrptonaught/serverutils/customMapLoader/CustomMapLoaderMod.java +++ b/src/main/java/net/kyrptonaught/serverutils/customMapLoader/CustomMapLoaderMod.java @@ -1,5 +1,6 @@ package net.kyrptonaught.serverutils.customMapLoader; + import com.mojang.brigadier.CommandDispatcher; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; @@ -7,10 +8,7 @@ import net.kyrptonaught.serverutils.ModuleWConfig; import net.kyrptonaught.serverutils.ServerUtilsMod; import net.kyrptonaught.serverutils.chestTracker.ChestTrackerMod; -import net.kyrptonaught.serverutils.customMapLoader.addons.BaseMapAddon; -import net.kyrptonaught.serverutils.customMapLoader.addons.BattleMapAddon; -import net.kyrptonaught.serverutils.customMapLoader.addons.LobbyMapAddon; -import net.kyrptonaught.serverutils.customMapLoader.addons.ResourcePackList; +import net.kyrptonaught.serverutils.customMapLoader.addons.*; import net.kyrptonaught.serverutils.customMapLoader.voting.HostOptions; import net.kyrptonaught.serverutils.customMapLoader.voting.Votebook; import net.kyrptonaught.serverutils.customWorldBorder.CustomWorldBorderMod; @@ -51,6 +49,8 @@ public class CustomMapLoaderMod extends ModuleWConfig { private static final HashMap LOADED_BATTLE_MAPS = new HashMap<>(); private static final HashMap LOADED_LOBBIES = new HashMap<>(); + public static final AddonResourcePackProvider ADDON_PROVIDER = new AddonResourcePackProvider(); + @Override public void onInitialize() { ServerLifecycleEvents.SERVER_STARTING.register(CustomMapLoaderMod::reloadAddonFiles); @@ -88,6 +88,7 @@ public static void reloadAddonFiles(MinecraftServer server) { players.get(i).networkHandler.reconfigure(); } } + } //todo fix @@ -116,8 +117,9 @@ public static void serverTick(MinecraftServer server) { continue; } - if (instance.runPreTriggerCondition(server)) + if (instance.runPreTriggerCondition(server)) { instance.executeDatapack(server); + } } } @@ -143,6 +145,8 @@ public static void battleLoad(MinecraftServer server, Identifier addon, Identifi return true; }); + ADDON_PROVIDER.loadAddon(addon, path); + tryEnableDatapack(server, config); instance.setDatapackFunctions(functions); LOADED_BATTLE_MAPS.put(dimID, instance); @@ -239,6 +243,9 @@ public static void prepareLobby(MinecraftServer server, Identifier addon, Identi teleportToLobby(dimID, players, null); + ADDON_PROVIDER.loadAddon(addon, path); + tryEnableDatapack(server, config); + if (functions != null) { for (CommandFunction commandFunction : functions) { server.getCommandFunctionManager().execute(commandFunction, server.getCommandSource().withLevel(2).withSilent()); @@ -313,15 +320,46 @@ private static void loadResourcePacks(BaseMapAddon addon, ServerPlayerEntity pla SwitchableResourcepacksMod.addPacks(list.packs, player); } + public static void tryEnableDatapack(MinecraftServer server, BaseMapAddon addon) { + server.getDataPackManager().scanPacks(); + if (server.getDataPackManager().hasProfile(AddonResourcePackProvider.getID(addon.addon_id))) { + server.getDataPackManager().enable(AddonResourcePackProvider.getID(addon.addon_id)); + server.reloadResources(server.getDataPackManager().getEnabledIds()).exceptionally(throwable -> { + throwable.printStackTrace(); + return null; + }); + } + } + + public static void tryDisableDatapack(MinecraftServer server, BaseMapAddon addon) { + server.getDataPackManager().scanPacks(); + if (server.getDataPackManager().hasProfile(AddonResourcePackProvider.getID(addon.addon_id))) { + server.getDataPackManager().disable(AddonResourcePackProvider.getID(addon.addon_id)); + server.reloadResources(server.getDataPackManager().getEnabledIds()).exceptionally(throwable -> { + throwable.printStackTrace(); + return null; + }); + } + } + public static void unloadLobbyMap(MinecraftServer server, Identifier dimID, Collection> functions) { + if (LOADED_LOBBIES.containsKey(dimID)) { +// tryDisableDatapack(server, LOADED_LOBBIES.get(dimID)); + ADDON_PROVIDER.unloadAddon(LOADED_LOBBIES.get(dimID).addon_id); + } + LOADED_LOBBIES.remove(dimID); DimensionLoaderMod.unLoadDimension(server, dimID, functions); } public static void unloadBattleMap(MinecraftServer server, Identifier dimID, Collection> functions) { - if (LOADED_BATTLE_MAPS.containsKey(dimID)) + if (LOADED_BATTLE_MAPS.containsKey(dimID)) { LOADED_BATTLE_MAPS.get(dimID).scheduleToRemove = true; + tryDisableDatapack(server, LOADED_BATTLE_MAPS.get(dimID).getAddon()); + ADDON_PROVIDER.unloadAddon(LOADED_BATTLE_MAPS.get(dimID).getAddon().addon_id); + } + DimensionLoaderMod.unLoadDimension(server, dimID, functions); } diff --git a/src/main/java/net/kyrptonaught/serverutils/customMapLoader/IO.java b/src/main/java/net/kyrptonaught/serverutils/customMapLoader/IO.java index 845952e..71b0b25 100644 --- a/src/main/java/net/kyrptonaught/serverutils/customMapLoader/IO.java +++ b/src/main/java/net/kyrptonaught/serverutils/customMapLoader/IO.java @@ -17,6 +17,7 @@ import net.minecraft.util.Identifier; import net.minecraft.world.dimension.DimensionType; +import java.io.IOException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.Path; @@ -95,13 +96,9 @@ public static void unZipMap(Path outputPath, Path filepath, String baseDirectory ZipEntry entry = entries.nextElement(); String entryName = FileHelper.fixPathSeparator(entry.getName()); if (entryName.startsWith(baseDirectory)) { - Path newOut = outputPath.resolve(entryName.replace(baseDirectory, "")); - if (entry.isDirectory()) { - Files.createDirectories(newOut); - } else { - Files.createDirectories(newOut.getParent()); - Files.copy(zip.getInputStream(entry), newOut, StandardCopyOption.REPLACE_EXISTING); - } + extractFile(zip, entry, outputPath.resolve(entryName.replace(baseDirectory, ""))); + } else if (entryName.startsWith("datapack/")) { + extractFile(zip, entry, outputPath.resolve(entryName)); } } catch (FileAlreadyExistsException ignored) { } catch (Exception e) { @@ -113,6 +110,15 @@ public static void unZipMap(Path outputPath, Path filepath, String baseDirectory } } + private static void extractFile(ZipFile zip, ZipEntry entry, Path newOut) throws IOException { + if (entry.isDirectory()) { + Files.createDirectories(newOut); + } else { + Files.createDirectories(newOut.getParent()); + Files.copy(zip.getInputStream(entry), newOut, StandardCopyOption.REPLACE_EXISTING); + } + } + public static DimensionType addDimensionType(MinecraftServer server, Path addonPath, Identifier dimID) { String dimJson = FileHelper.readFileFromZip(addonPath, "dimension_type.json"); if (dimJson != null) { diff --git a/src/main/java/net/kyrptonaught/serverutils/customMapLoader/addons/AddonResourcePackProvider.java b/src/main/java/net/kyrptonaught/serverutils/customMapLoader/addons/AddonResourcePackProvider.java new file mode 100644 index 0000000..67a728a --- /dev/null +++ b/src/main/java/net/kyrptonaught/serverutils/customMapLoader/addons/AddonResourcePackProvider.java @@ -0,0 +1,84 @@ +package net.kyrptonaught.serverutils.customMapLoader.addons; + +import net.minecraft.resource.*; +import net.minecraft.resource.fs.ResourceFileSystem; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.path.SymlinkEntry; +import net.minecraft.util.path.SymlinkFinder; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +public class AddonResourcePackProvider implements ResourcePackProvider { + public static final ResourcePackSource LEMADDON = ResourcePackSource.create(name -> name, true); + private static final ResourcePackPosition POSITION = new ResourcePackPosition(false, ResourcePackProfile.InsertionPosition.TOP, false); + + private final HashMap loadedAddons = new HashMap<>(); + + public void loadAddon(Identifier id, Path path) { + loadedAddons.put(id, path.resolve("datapack")); + } + + public void unloadAddon(Identifier id) { + loadedAddons.remove(id); + } + + @Override + public void register(Consumer profileAdder) { + loadedAddons.forEach((id, path) -> { + try { + ResourcePackProfile.PackFactory packFactory = new PackOpenerImpl(new SymlinkFinder(path2 -> true)).open(path, List.of()); + + ResourcePackInfo resourcePackInfo = new ResourcePackInfo(getID(id), Text.literal(id.toString()), LEMADDON, Optional.empty()); + ResourcePackProfile resourcePackProfile = ResourcePackProfile.create(resourcePackInfo, packFactory, ResourceType.SERVER_DATA, POSITION); + if (resourcePackProfile != null) { + profileAdder.accept(resourcePackProfile); + } + } catch (IOException iOException) { + System.out.println("Error loading lemaddon data pack: " + id); + } + + }); + + } + + public static String getID(Identifier identifier) { + return "lemaddon/" + identifier; + } + + static class PackOpenerImpl extends ResourcePackOpener { + protected PackOpenerImpl(SymlinkFinder symlinkFinder) { + super(symlinkFinder); + } + + @Nullable + @Override + public ResourcePackProfile.PackFactory open(Path path, List foundSymlinks) throws IOException { + return new DirectoryResourcePack.DirectoryBackedFactory(path); + } + + @Nullable + @Override + protected ResourcePackProfile.PackFactory openZip(Path path) { + FileSystem fileSystem = path.getFileSystem(); + if (fileSystem == FileSystems.getDefault() || fileSystem instanceof ResourceFileSystem) { + return new ZipResourcePack.ZipBackedFactory(path); + } + return null; + } + + @Nullable + @Override + protected ResourcePackProfile.PackFactory openDirectory(Path path) { + return new DirectoryResourcePack.DirectoryBackedFactory(path); + } + } +} diff --git a/src/main/java/net/kyrptonaught/serverutils/mixin/customMapLoader/VanillaDataPackProviderMixin.java b/src/main/java/net/kyrptonaught/serverutils/mixin/customMapLoader/VanillaDataPackProviderMixin.java new file mode 100644 index 0000000..450d990 --- /dev/null +++ b/src/main/java/net/kyrptonaught/serverutils/mixin/customMapLoader/VanillaDataPackProviderMixin.java @@ -0,0 +1,23 @@ +package net.kyrptonaught.serverutils.mixin.customMapLoader; + +import net.kyrptonaught.serverutils.customMapLoader.CustomMapLoaderMod; +import net.minecraft.resource.ResourcePackProvider; +import net.minecraft.resource.VanillaDataPackProvider; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArgs; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +import java.util.Arrays; + +@Mixin(VanillaDataPackProvider.class) +public class VanillaDataPackProviderMixin { + + + @ModifyArgs(method = "createManager(Ljava/nio/file/Path;Lnet/minecraft/util/path/SymlinkFinder;)Lnet/minecraft/resource/ResourcePackManager;", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;([Lnet/minecraft/resource/ResourcePackProvider;)V")) + private static void registerAddonProvider(Args args) { + ResourcePackProvider[] packs = Arrays.copyOf(((ResourcePackProvider[]) args.get(0)), ((ResourcePackProvider[]) args.get(0)).length + 1); + packs[packs.length - 1] = CustomMapLoaderMod.ADDON_PROVIDER; + args.set(0, packs); + } +} diff --git a/src/main/resources/serverutils.mixins.json b/src/main/resources/serverutils.mixins.json index 3eb5412..a5f4131 100644 --- a/src/main/resources/serverutils.mixins.json +++ b/src/main/resources/serverutils.mixins.json @@ -16,6 +16,7 @@ "critBlocker.PlayerEntityMixin", "customMapLoader.ServerPlayNetworkHandlerMixin", "customMapLoader.SimpleRegistryMixin", + "customMapLoader.VanillaDataPackProviderMixin", "customWorldBorder.PlayerManagerMixin", "customWorldBorder.WorldBorderMixin", "dimensionLoader.PlayerManagerMixin",