diff --git a/Jenkinsfile b/Jenkinsfile index ce3cb489e..3143b765b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -52,8 +52,8 @@ pipeline { ]){ sh './gradlew ${GRADLE_ARGS} :forge:publish -PforgeMavenUser=${FORGE_MAVEN_USR} -PforgeMavenPassword=${FORGE_MAVEN_PSW} -PkeystoreKeyPass=${KEYSTORE_KEYPASS} -PkeystoreStorePass=${KEYSTORE_STOREPASS} -Pkeystore=${KEYSTORE} -PcrowdinKey=${CROWDIN}' } - //We're testing so use the test group - sh 'curl --user ${FORGE_MAVEN} http://files.minecraftforge.net/maven/manage/promote/latest/net.minecraftforge.test.forge/${MYVERSION}' + //We're not testing anymore so don't use the test group + sh 'curl --user ${FORGE_MAVEN} http://files.minecraftforge.net/maven/manage/promote/latest/net.minecraftforge.forge/${MYVERSION}' } } stage('test_publish_pr') { //Publish to local repo to test full process, but don't include credentials so it can't sign/publish to maven diff --git a/src/main/java/net/minecraftforge/fml/LogicalSidedProvider.java b/src/main/java/net/minecraftforge/fml/LogicalSidedProvider.java index 85c0d8b71..03eafed1e 100644 --- a/src/main/java/net/minecraftforge/fml/LogicalSidedProvider.java +++ b/src/main/java/net/minecraftforge/fml/LogicalSidedProvider.java @@ -27,7 +27,9 @@ import java.util.function.Supplier; public enum LogicalSidedProvider { - WORKQUEUE((c)->c.get(), (s)->s.get()); + WORKQUEUE((c)->c.get(), (s)->s.get()), + INSTANCE((c)->c.get(), (s)->s.get()) + ; private static Supplier client; private static Supplier server; diff --git a/src/main/java/net/minecraftforge/fml/network/PacketDistributor.java b/src/main/java/net/minecraftforge/fml/network/PacketDistributor.java new file mode 100644 index 000000000..6f8277eeb --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/network/PacketDistributor.java @@ -0,0 +1,265 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library 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 version 2.1 + * of the License. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.network; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.dimension.DimensionType; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.LogicalSidedProvider; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Means to distribute packets in various ways + * + * @see net.minecraftforge.fml.network.simple.SimpleChannel#send(PacketTarget, Object) + * + * @param + */ +public class PacketDistributor { + /** + * Send to the player specified in the Supplier + *
+ * {@link #with(Supplier)} Player + */ + public static final PacketDistributor PLAYER = new PacketDistributor<>(PacketDistributor::playerConsumer, NetworkDirection.PLAY_TO_CLIENT); + /** + * Send to everyone in the dimension specified in the Supplier + *
+ * {@link #with(Supplier)} DimensionType + */ + public static final PacketDistributor DIMENSION = new PacketDistributor<>(PacketDistributor::playerListDimConsumer, NetworkDirection.PLAY_TO_CLIENT); + /** + * Send to everyone near the {@link TargetPoint} specified in the Supplier + *
+ * {@link #with(Supplier)} TargetPoint + */ + public static final PacketDistributor NEAR = new PacketDistributor<>(PacketDistributor::playerListPointConsumer, NetworkDirection.PLAY_TO_CLIENT); + /** + * Send to everyone + *
+ * {@link #noArg()} + */ + public static final PacketDistributor ALL = new PacketDistributor<>(PacketDistributor::playerListAll, NetworkDirection.PLAY_TO_CLIENT); + /** + * Send to the server (CLIENT to SERVER) + *
+ * {@link #noArg()} + */ + public static final PacketDistributor SERVER = new PacketDistributor<>(PacketDistributor::clientToServer, NetworkDirection.PLAY_TO_SERVER); + /** + * Send to all tracking the Entity in the Supplier + *
+ * {@link #with(Supplier)} Entity + */ + public static final PacketDistributor TRACKING_ENTITY = new PacketDistributor<>(PacketDistributor::trackingEntity, NetworkDirection.PLAY_TO_CLIENT); + /** + * Send to all tracking the Entity and Player in the Supplier + *
+ * {@link #with(Supplier)} Entity + */ + public static final PacketDistributor TRACKING_ENTITY_AND_SELF = new PacketDistributor<>(PacketDistributor::trackingEntityAndSelf, NetworkDirection.PLAY_TO_CLIENT); + /** + * Send to all tracking the Chunk in the Supplier + *
+ * {@link #with(Supplier)} Chunk + */ + public static final PacketDistributor TRACKING_CHUNK = new PacketDistributor<>(PacketDistributor::trackingChunk, NetworkDirection.PLAY_TO_CLIENT); + /** + * Send to the supplied list of NetworkManager instances in the Supplier + *
+ * {@link #with(Supplier)} List of NetworkManager + */ + public static final PacketDistributor> NMLIST = new PacketDistributor<>(PacketDistributor::networkManagerList, NetworkDirection.PLAY_TO_CLIENT); + + public static final class TargetPoint { + + private final EntityPlayerMP excluded; + private final double x; + private final double y; + private final double z; + private final double r2; + private final DimensionType dim; + + /** + * A target point with excluded entity + * + * @param excluded Entity to exclude + * @param x X + * @param y Y + * @param z Z + * @param r2 Radius + * @param dim DimensionType + */ + public TargetPoint(final EntityPlayerMP excluded, final double x, final double y, final double z, final double r2, final DimensionType dim) { + this.excluded = excluded; + this.x = x; + this.y = y; + this.z = z; + this.r2 = r2; + this.dim = dim; + } + + /** + * A target point without excluded entity + * @param x X + * @param y Y + * @param z Z + * @param r2 Radius + * @param dim DimensionType + */ + public TargetPoint(final double x, final double y, final double z, final double r2, final DimensionType dim) { + this.excluded = null; + this.x = x; + this.y = y; + this.z = z; + this.r2 = r2; + this.dim = dim; + } + + /** + * Helper to build a TargetPoint without excluded Entity + * @param x X + * @param y Y + * @param z Z + * @param r2 Radius + * @param dim DimensionType + * @return A TargetPoint supplier + */ + public static Supplier p(double x, double y, double z, double r2, DimensionType dim) { + TargetPoint tp = new TargetPoint(x, y, z, r2, dim); + return ()->tp; + } + + } + + /** + * A Distributor curried with a specific value instance, for actual dispatch + * + * @see net.minecraftforge.fml.network.simple.SimpleChannel#send(PacketTarget, Object) + * + */ + public static class PacketTarget { + private final Consumer> packetConsumer; + private final PacketDistributor distributor; + PacketTarget(final Consumer> packetConsumer, final PacketDistributor distributor) { + this.packetConsumer = packetConsumer; + this.distributor = distributor; + } + + public void send(Packet packet) { + packetConsumer.accept(packet); + } + + public NetworkDirection getDirection() { + return distributor.direction; + } + + } + + private final BiFunction, Supplier, Consumer>> functor; + private final NetworkDirection direction; + + public PacketDistributor(BiFunction, Supplier, Consumer>> functor, NetworkDirection direction) { + this.functor = functor; + this.direction = direction; + } + + /** + * Apply the supplied value to the specific distributor to generate an instance for sending packets to. + * @param input The input to apply + * @return A curried instance + */ + public PacketTarget with(Supplier input) { + return new PacketTarget(functor.apply(this, input), this); + } + + /** + * Apply a no argument value to a distributor to generate an instance for sending packets to. + * + * @see #ALL + * @see #SERVER + * @return A curried instance + */ + public PacketTarget noArg() { + return new PacketTarget(functor.apply(this, ()->null), this); + } + + private Consumer> playerConsumer(final Supplier entityPlayerMPSupplier) { + return p -> entityPlayerMPSupplier.get().connection.netManager.sendPacket(p); + } + private Consumer> playerListDimConsumer(final Supplier dimensionTypeSupplier) { + return p->getServer().getPlayerList().sendPacketToAllPlayersInDimension(p, dimensionTypeSupplier.get()); + } + + private Consumer> playerListAll(final Supplier voidSupplier) { + return p -> getServer().getPlayerList().sendPacketToAllPlayers(p); + } + + private Consumer> clientToServer(final Supplier voidSupplier) { + return p -> Minecraft.getInstance().getConnection().sendPacket(p); + } + + private Consumer> playerListPointConsumer(final Supplier targetPointSupplier) { + return p -> { + final TargetPoint tp = targetPointSupplier.get(); + getServer().getPlayerList().sendToAllNearExcept(tp.excluded, tp.x, tp.y, tp.z, tp.r2, tp.dim, p); + }; + } + + private Consumer> trackingEntity(final Supplier entitySupplier) { + return p-> { + final Entity entity = entitySupplier.get(); + getServer().getWorld(entity.dimension).getEntityTracker().sendToTracking(entity, p); + }; + } + + private Consumer> trackingEntityAndSelf(final Supplier entitySupplier) { + return p-> { + final Entity entity = entitySupplier.get(); + getServer().getWorld(entity.dimension).getEntityTracker().sendToTrackingAndSelf(entity, p); + }; + } + + private Consumer> trackingChunk(final Supplier chunkPosSupplier) { + return p -> { + final Chunk chunk = chunkPosSupplier.get(); + ((WorldServer)chunk.getWorld()).getPlayerChunkMap().getEntry(chunk.x, chunk.z).sendPacket(p); + }; + } + + private Consumer> networkManagerList(final Supplier> nmListSupplier) { + return p -> nmListSupplier.get().forEach(nm->nm.sendPacket(p)); + } + + private MinecraftServer getServer() { + return LogicalSidedProvider.INSTANCE.get(LogicalSide.SERVER); + } +} diff --git a/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java b/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java index aba1c15a1..030914407 100644 --- a/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java +++ b/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java @@ -24,6 +24,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.PacketBuffer; +import net.minecraft.world.dimension.DimensionType; import net.minecraftforge.fml.network.*; import org.apache.commons.lang3.tuple.Pair; @@ -86,6 +87,21 @@ public class SimpleChannel manager.sendPacket(toVanillaPacket(message, direction)); } + /** + * Send a message to the {@link PacketDistributor.PacketTarget} from a {@link PacketDistributor} instance. + * + *
+     *     channel.send(PacketDistributor.PLAYER.with(()->player), message)
+     * 
+ * + * @param target The curried target from a PacketDistributor + * @param message The message to send + * @param The type of the message + */ + public void send(PacketDistributor.PacketTarget target, MSG message) { + target.send(toVanillaPacket(message, target.getDirection())); + } + public Packet toVanillaPacket(MSG message, NetworkDirection direction) { return direction.buildPacket(toBuffer(message), instance.getChannelName()).getThis();