Add a simple network API..

Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
cpw 2019-02-18 15:08:57 -05:00
parent 2e2c57dbd1
commit 70be790b2a
No known key found for this signature in database
GPG key ID: 8EB3DF749553B1B7
4 changed files with 286 additions and 3 deletions

4
Jenkinsfile vendored
View file

@ -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}' 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 //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.test.forge/${MYVERSION}' 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 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

View file

@ -27,7 +27,9 @@ import java.util.function.Supplier;
public enum LogicalSidedProvider 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<Minecraft> client; private static Supplier<Minecraft> client;
private static Supplier<MinecraftServer> server; private static Supplier<MinecraftServer> server;

View file

@ -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 <T>
*/
public class PacketDistributor<T> {
/**
* Send to the player specified in the Supplier
* <br/>
* {@link #with(Supplier)} Player
*/
public static final PacketDistributor<EntityPlayerMP> PLAYER = new PacketDistributor<>(PacketDistributor::playerConsumer, NetworkDirection.PLAY_TO_CLIENT);
/**
* Send to everyone in the dimension specified in the Supplier
* <br/>
* {@link #with(Supplier)} DimensionType
*/
public static final PacketDistributor<DimensionType> DIMENSION = new PacketDistributor<>(PacketDistributor::playerListDimConsumer, NetworkDirection.PLAY_TO_CLIENT);
/**
* Send to everyone near the {@link TargetPoint} specified in the Supplier
* <br/>
* {@link #with(Supplier)} TargetPoint
*/
public static final PacketDistributor<TargetPoint> NEAR = new PacketDistributor<>(PacketDistributor::playerListPointConsumer, NetworkDirection.PLAY_TO_CLIENT);
/**
* Send to everyone
* <br/>
* {@link #noArg()}
*/
public static final PacketDistributor<Void> ALL = new PacketDistributor<>(PacketDistributor::playerListAll, NetworkDirection.PLAY_TO_CLIENT);
/**
* Send to the server (CLIENT to SERVER)
* <br/>
* {@link #noArg()}
*/
public static final PacketDistributor<Void> SERVER = new PacketDistributor<>(PacketDistributor::clientToServer, NetworkDirection.PLAY_TO_SERVER);
/**
* Send to all tracking the Entity in the Supplier
* <br/>
* {@link #with(Supplier)} Entity
*/
public static final PacketDistributor<Entity> TRACKING_ENTITY = new PacketDistributor<>(PacketDistributor::trackingEntity, NetworkDirection.PLAY_TO_CLIENT);
/**
* Send to all tracking the Entity and Player in the Supplier
* <br/>
* {@link #with(Supplier)} Entity
*/
public static final PacketDistributor<Entity> TRACKING_ENTITY_AND_SELF = new PacketDistributor<>(PacketDistributor::trackingEntityAndSelf, NetworkDirection.PLAY_TO_CLIENT);
/**
* Send to all tracking the Chunk in the Supplier
* <br/>
* {@link #with(Supplier)} Chunk
*/
public static final PacketDistributor<Chunk> TRACKING_CHUNK = new PacketDistributor<>(PacketDistributor::trackingChunk, NetworkDirection.PLAY_TO_CLIENT);
/**
* Send to the supplied list of NetworkManager instances in the Supplier
* <br/>
* {@link #with(Supplier)} List of NetworkManager
*/
public static final PacketDistributor<List<NetworkManager>> 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<TargetPoint> 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<Packet<?>> packetConsumer;
private final PacketDistributor<?> distributor;
PacketTarget(final Consumer<Packet<?>> 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<PacketDistributor<T>, Supplier<T>, Consumer<Packet<?>>> functor;
private final NetworkDirection direction;
public PacketDistributor(BiFunction<PacketDistributor<T>, Supplier<T>, Consumer<Packet<?>>> 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<T> 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<Packet<?>> playerConsumer(final Supplier<EntityPlayerMP> entityPlayerMPSupplier) {
return p -> entityPlayerMPSupplier.get().connection.netManager.sendPacket(p);
}
private Consumer<Packet<?>> playerListDimConsumer(final Supplier<DimensionType> dimensionTypeSupplier) {
return p->getServer().getPlayerList().sendPacketToAllPlayersInDimension(p, dimensionTypeSupplier.get());
}
private Consumer<Packet<?>> playerListAll(final Supplier<Void> voidSupplier) {
return p -> getServer().getPlayerList().sendPacketToAllPlayers(p);
}
private Consumer<Packet<?>> clientToServer(final Supplier<Void> voidSupplier) {
return p -> Minecraft.getInstance().getConnection().sendPacket(p);
}
private Consumer<Packet<?>> playerListPointConsumer(final Supplier<TargetPoint> 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<Packet<?>> trackingEntity(final Supplier<Entity> entitySupplier) {
return p-> {
final Entity entity = entitySupplier.get();
getServer().getWorld(entity.dimension).getEntityTracker().sendToTracking(entity, p);
};
}
private Consumer<Packet<?>> trackingEntityAndSelf(final Supplier<Entity> entitySupplier) {
return p-> {
final Entity entity = entitySupplier.get();
getServer().getWorld(entity.dimension).getEntityTracker().sendToTrackingAndSelf(entity, p);
};
}
private Consumer<Packet<?>> trackingChunk(final Supplier<Chunk> chunkPosSupplier) {
return p -> {
final Chunk chunk = chunkPosSupplier.get();
((WorldServer)chunk.getWorld()).getPlayerChunkMap().getEntry(chunk.x, chunk.z).sendPacket(p);
};
}
private Consumer<Packet<?>> networkManagerList(final Supplier<List<NetworkManager>> nmListSupplier) {
return p -> nmListSupplier.get().forEach(nm->nm.sendPacket(p));
}
private MinecraftServer getServer() {
return LogicalSidedProvider.INSTANCE.get(LogicalSide.SERVER);
}
}

View file

@ -24,6 +24,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.fml.network.*; import net.minecraftforge.fml.network.*;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@ -86,6 +87,21 @@ public class SimpleChannel
manager.sendPacket(toVanillaPacket(message, direction)); manager.sendPacket(toVanillaPacket(message, direction));
} }
/**
* Send a message to the {@link PacketDistributor.PacketTarget} from a {@link PacketDistributor} instance.
*
* <pre>
* channel.send(PacketDistributor.PLAYER.with(()->player), message)
* </pre>
*
* @param target The curried target from a PacketDistributor
* @param message The message to send
* @param <MSG> The type of the message
*/
public <MSG> void send(PacketDistributor.PacketTarget target, MSG message) {
target.send(toVanillaPacket(message, target.getDirection()));
}
public <MSG> Packet<?> toVanillaPacket(MSG message, NetworkDirection direction) public <MSG> Packet<?> toVanillaPacket(MSG message, NetworkDirection direction)
{ {
return direction.buildPacket(toBuffer(message), instance.getChannelName()).getThis(); return direction.buildPacket(toBuffer(message), instance.getChannelName()).getThis();