diff --git a/README.md b/README.md index bfe62716..d4faea59 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,14 @@ Architectury Plugin. ### Getting started with making multiplatform mods -Gradle Plugin: https://github.com/architectury/architectury-plugin +Architectury Loom: https://github.com/architectury/architectury-loom (a fork of Fabric Loom adding multiplatform development capabilities) +Gradle Plugin: https://github.com/architectury/architectury-plugin (includes Architectury Injectables, for the `@ExpectPlatform` annotation) +Example Mod: https://github.com/architectury/architectury-example-mod (a discontinued example mod using Architectury, if possible, use the templates instead) +Mod Templates: https://github.com/architectury/architectury-templates (a set of templates to get started using the Architectury toolchain) -Example Mod: https://github.com/architectury/architectury-example-mod +### Example: Usage of @ExpectPlatform +![Exmaple of the @ExpectPlatform annotation, part of Architectury Injectables](https://camo.githubusercontent.com/78c68766affb70fbd88f9806e0e95f78765ec339448d7102065f2942be2b3215/68747470733a2f2f6d656469612e646973636f72646170702e6e65742f6174746163686d656e74732f3538363138363230323738313138383130382f3737363432383831343330393738353632302f756e6b6e6f776e2e706e673f77696474683d31313931266865696768743d343339) ### Credits -This library bundles typetools, which you can find its -license [here](https://github.com/jhalterman/typetools/blob/master/LICENSE.txt "") +In certain older versions, this library used to bundle typetools; you can find its license [here](https://github.com/jhalterman/typetools/blob/master/LICENSE.txt "") diff --git a/common/src/main/java/dev/architectury/networking/transformers/SplitPacketTransformer.java b/common/src/main/java/dev/architectury/networking/transformers/SplitPacketTransformer.java index b5287478..7214b3d7 100644 --- a/common/src/main/java/dev/architectury/networking/transformers/SplitPacketTransformer.java +++ b/common/src/main/java/dev/architectury/networking/transformers/SplitPacketTransformer.java @@ -179,7 +179,7 @@ public class SplitPacketTransformer implements PacketTransformer { @Override public void outbound(NetworkManager.Side side, ResourceLocation id, FriendlyByteBuf buf, TransformationSink sink) { - int maxSize = (side == NetworkManager.Side.C2S ? 32767 : 1048576) - 1 - 10; + int maxSize = (side == NetworkManager.Side.C2S ? 32767 : 1048576) - 1 - 20; if (buf.readableBytes() <= maxSize) { ByteBuf stateBuf = Unpooled.buffer(1); stateBuf.writeByte(ONLY); @@ -187,7 +187,7 @@ public class SplitPacketTransformer implements PacketTransformer { sink.accept(side, id, packetBuffer); } else { int partSize = maxSize - 4; - int parts = Math.round(buf.readableBytes() / (float) partSize); + int parts = (int) Math.ceil(buf.readableBytes() / (float) partSize); for (int i = 0; i < parts; i++) { FriendlyByteBuf packetBuffer = new FriendlyByteBuf(Unpooled.buffer()); if (i == 0) { diff --git a/common/src/main/java/dev/architectury/platform/Mod.java b/common/src/main/java/dev/architectury/platform/Mod.java index 117cc795..68e67cb4 100644 --- a/common/src/main/java/dev/architectury/platform/Mod.java +++ b/common/src/main/java/dev/architectury/platform/Mod.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import java.nio.file.Path; import java.util.Collection; +import java.util.List; import java.util.Optional; public interface Mod { @@ -45,8 +46,30 @@ public interface Mod { */ Optional getLogoFile(int preferredSize); + /** + * Gets a list of all possible root paths for the mod. + * This is especially relevant on Fabric, as a single mod may have multiple source sets + * (such as client / server-specific ones), each corresponding to one root path. + * + * @return A list of root paths belonging to the mod + */ + List getFilePaths(); + + /** + * @deprecated Use {@link #getFilePaths()} instead + */ + @Deprecated(forRemoval = true) Path getFilePath(); + /** + * Gets an NIO Path to the given resource contained within the mod file / folder. + * The path is verified to exist, and an empty optional is returned if it doesn't. + * + * @param path The resource to search for + * @return The path of the resource if it exists, or {@link Optional#empty()} if it doesn't + */ + Optional findResource(String... path); + Collection getAuthors(); @Nullable diff --git a/fabric/build.gradle b/fabric/build.gradle index 8efa1b1a..b3db0713 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -139,7 +139,7 @@ modrinth { changelog = releaseChangelog() uploadFile = remapJar gameVersions = ["1.19-pre1"] - loaders = ["fabric"] + loaders = ["fabric", "quilt"] dependencies { // TODO: move to slugs if that functionality becomes available in minotaur required.project("P7dR8mSH") // Fabric API diff --git a/fabric/src/main/java/dev/architectury/hooks/level/entity/fabric/FakePlayers.java b/fabric/src/main/java/dev/architectury/hooks/level/entity/fabric/FakePlayers.java new file mode 100644 index 00000000..41d736b6 --- /dev/null +++ b/fabric/src/main/java/dev/architectury/hooks/level/entity/fabric/FakePlayers.java @@ -0,0 +1,31 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.hooks.level.entity.fabric; + +import dev.architectury.event.Event; +import dev.architectury.event.EventFactory; +import dev.architectury.event.EventResult; +import net.minecraft.world.entity.player.Player; + +public interface FakePlayers { + Event EVENT = EventFactory.createEventResult(); + + EventResult isFakePlayer(Player player); +} diff --git a/fabric/src/main/java/dev/architectury/hooks/level/entity/fabric/PlayerHooksImpl.java b/fabric/src/main/java/dev/architectury/hooks/level/entity/fabric/PlayerHooksImpl.java index d1014a45..d5a76347 100644 --- a/fabric/src/main/java/dev/architectury/hooks/level/entity/fabric/PlayerHooksImpl.java +++ b/fabric/src/main/java/dev/architectury/hooks/level/entity/fabric/PlayerHooksImpl.java @@ -19,10 +19,17 @@ package dev.architectury.hooks.level.entity.fabric; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; public class PlayerHooksImpl { public static boolean isFake(Player player) { - return false; + var result = FakePlayers.EVENT.invoker().isFakePlayer(player); + if (result.isPresent()) { + return result.isTrue(); + } + // If no result has been returned, assume that player classes extending ServerPlayer + // (apart from ServerPlayer itself) are fake players, as a "reasonable default" + return player instanceof ServerPlayer && player.getClass() != ServerPlayer.class; } } diff --git a/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java b/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java index 8dadf8a9..bf11e5a2 100644 --- a/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java +++ b/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java @@ -30,6 +30,7 @@ import org.jetbrains.annotations.Nullable; import java.nio.file.Path; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -121,12 +122,22 @@ public class PlatformImpl { public Optional getLogoFile(int preferredSize) { return metadata.getIconPath(preferredSize); } - + + @Override + public List getFilePaths() { + return container.getRootPaths(); + } + @Override public Path getFilePath() { return container.getRootPath(); } - + + @Override + public Optional findResource(String... path) { + return container.findPath(String.join("/", path)); + } + @Override public Collection getAuthors() { return metadata.getAuthors().stream() diff --git a/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java b/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java index 19a9ece3..f39b80e4 100644 --- a/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java +++ b/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java @@ -35,6 +35,7 @@ import org.jetbrains.annotations.Nullable; import javax.annotation.Nonnull; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -127,9 +128,19 @@ public class PlatformImpl { return this.info.getLogoFile(); } + @Override + public List getFilePaths() { + return List.of(getFilePath()); + } + @Override public Path getFilePath() { - return this.info.getOwningFile().getFile().getFilePath(); + return this.info.getOwningFile().getFile().getSecureJar().getRootPath(); + } + + @Override + public Optional findResource(String... path) { + return Optional.of(this.info.getOwningFile().getFile().findResource(path)).filter(Files::exists); } @Override diff --git a/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java b/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java index 65a8a5d0..c65e551c 100644 --- a/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java +++ b/testmod-common/src/main/java/dev/architectury/test/networking/TestModNet.java @@ -41,7 +41,7 @@ public interface TestModNet { // An example Server to Client message MessageType SYNC_DATA = NET.registerS2C("sync_data", SyncDataMessage::new); ResourceLocation BIG_DATA = new ResourceLocation(TestMod.MOD_ID, "big_data"); - String BIG_STRING = StringUtils.repeat('a', 60000); + String BIG_STRING = StringUtils.repeat('a', 100000); static void initialize() { NetworkManager.registerReceiver(NetworkManager.Side.C2S, BIG_DATA, Collections.singletonList(new SplitPacketTransformer()), (buf, context) -> {