work on packets and networking
This commit is contained in:
parent
df1b7f0963
commit
dece4d851a
26 changed files with 602 additions and 603 deletions
|
@ -1,127 +0,0 @@
|
|||
package at.petrak.hexcasting
|
||||
|
||||
import at.petrak.hexcasting.api.PatternRegistry
|
||||
import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers
|
||||
import at.petrak.hexcasting.api.mod.HexConfig
|
||||
import at.petrak.hexcasting.api.mod.HexStatistics
|
||||
import at.petrak.hexcasting.api.player.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.client.*
|
||||
import at.petrak.hexcasting.common.blocks.HexBlockEntities
|
||||
import at.petrak.hexcasting.common.blocks.HexBlocks
|
||||
import at.petrak.hexcasting.common.casting.RegisterPatterns
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.great.OpFlight
|
||||
import at.petrak.hexcasting.common.command.HexCommands
|
||||
import at.petrak.hexcasting.common.command.PatternResLocArgument
|
||||
import at.petrak.hexcasting.common.entities.HexEntities
|
||||
import at.petrak.hexcasting.common.items.HexItems
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilityHandler
|
||||
import at.petrak.hexcasting.common.lib.HexSounds
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping
|
||||
import at.petrak.hexcasting.common.network.HexMessages
|
||||
import at.petrak.hexcasting.common.particles.HexParticles
|
||||
import at.petrak.hexcasting.common.recipe.HexComposting
|
||||
import at.petrak.hexcasting.common.recipe.HexCustomRecipes
|
||||
import at.petrak.hexcasting.common.recipe.HexRecipeSerializers
|
||||
import at.petrak.hexcasting.datagen.HexDataGenerators
|
||||
import at.petrak.hexcasting.datagen.lootmods.HexLootModifiers
|
||||
import at.petrak.hexcasting.server.TickScheduler
|
||||
import net.minecraft.commands.synchronization.ArgumentTypes
|
||||
import net.minecraft.commands.synchronization.EmptyArgumentSerializer
|
||||
import net.minecraftforge.api.distmarker.Dist
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.DistExecutor
|
||||
import net.minecraftforge.fml.ModLoadingContext
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.config.ModConfig
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
@Mod(HexMod.MOD_ID)
|
||||
object HexMod {
|
||||
// hmm today I will use a popular logging framework :clueless:
|
||||
val LOGGER: Logger = LoggerFactory.getLogger(HexMod::class.java)
|
||||
|
||||
val CONFIG_SPEC: ForgeConfigSpec
|
||||
val SERVER_CONFIG_SPEC: ForgeConfigSpec
|
||||
val CLIENT_CONFIG_SPEC: ForgeConfigSpec
|
||||
|
||||
// mumblemumble thanks shy mumble mumble
|
||||
const val MOD_ID = "hexcasting"
|
||||
|
||||
init {
|
||||
CONFIG_SPEC = ForgeConfigSpec.Builder()
|
||||
.configure { builder: ForgeConfigSpec.Builder? -> HexConfig(builder) }.right
|
||||
SERVER_CONFIG_SPEC = ForgeConfigSpec.Builder()
|
||||
.configure { builder: ForgeConfigSpec.Builder? -> HexConfig.Server(builder) }.right
|
||||
CLIENT_CONFIG_SPEC = ForgeConfigSpec.Builder()
|
||||
.configure { builder: ForgeConfigSpec.Builder? -> HexConfig.Client(builder) }.right
|
||||
|
||||
ArgumentTypes.register("hexcasting:pattern", PatternResLocArgument::class.java, EmptyArgumentSerializer(PatternResLocArgument::id))
|
||||
|
||||
// mod lifecycle
|
||||
val modBus = thedarkcolour.kotlinforforge.forge.MOD_BUS
|
||||
// game events
|
||||
val evBus = thedarkcolour.kotlinforforge.forge.FORGE_BUS
|
||||
|
||||
modBus.register(this)
|
||||
// gotta do it at *some* point
|
||||
modBus.register(RegisterPatterns::class.java)
|
||||
modBus.register(HexDataGenerators::class.java)
|
||||
|
||||
HexItems.ITEMS.register(modBus)
|
||||
HexBlocks.BLOCKS.register(modBus)
|
||||
HexBlockEntities.BLOCK_ENTITIES.register(modBus)
|
||||
HexEntities.ENTITIES.register(modBus)
|
||||
HexLootModifiers.LOOT_MODS.register(modBus)
|
||||
HexSounds.SOUNDS.register(modBus)
|
||||
HexParticles.PARTICLES.register(modBus)
|
||||
HexCustomRecipes.RECIPES.register(modBus)
|
||||
HexRecipeSerializers.SERIALIZERS.register(modBus)
|
||||
modBus.register(HexStatistics::class.java)
|
||||
modBus.register(HexRecipeSerializers::class.java)
|
||||
|
||||
modBus.register(HexComposting::class.java)
|
||||
|
||||
evBus.register(HexCommands::class.java)
|
||||
evBus.register(TickScheduler)
|
||||
evBus.register(HexCapabilityHandler::class.java)
|
||||
evBus.register(HexPlayerDataHelper::class.java)
|
||||
evBus.register(OpFlight)
|
||||
evBus.register(Brainsweeping::class.java)
|
||||
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT) {
|
||||
Runnable {
|
||||
modBus.register(RegisterClientStuff::class.java)
|
||||
evBus.register(ClientTickCounter::class.java)
|
||||
evBus.register(HexAdditionalRenderers::class.java)
|
||||
evBus.register(ShiftScrollListener::class.java)
|
||||
evBus.register(HexTooltips::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
// and then things that don't require busses
|
||||
HexMessages.register()
|
||||
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CONFIG_SPEC)
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_CONFIG_SPEC)
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, CLIENT_CONFIG_SPEC)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun commonSetup(evt: FMLCommonSetupEvent) {
|
||||
evt.enqueueWork { HexAdvancementTriggers.registerTriggers() }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getLogger() = this.LOGGER
|
||||
|
||||
@SubscribeEvent
|
||||
fun printPatternCount(evt: FMLLoadCompleteEvent) {
|
||||
getLogger().info(
|
||||
PatternRegistry.getPatternCountInfo()
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package at.petrak.hexcasting.api;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
@ -24,4 +25,8 @@ public interface HexAPI {
|
|||
static HexAPI instance() {
|
||||
return INSTANCE.get();
|
||||
}
|
||||
|
||||
static ResourceLocation modLoc(String s) {
|
||||
return new ResourceLocation(MOD_ID, s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package at.petrak.hexcasting.api.mod;
|
||||
|
||||
// Don't understand what this does so i commented it all out :gigachad:
|
||||
/*
|
||||
|
||||
import at.petrak.hexcasting.api.misc.FrozenColorizer;
|
||||
import at.petrak.hexcasting.api.player.Sentinel;
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray;
|
||||
|
@ -44,3 +47,5 @@ public final class HexApiMessages {
|
|||
return particleSprayMessage.apply(spray, colorizer);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package at.petrak.hexcasting.common.lib;
|
||||
|
||||
/**
|
||||
* Tags, capability keys, etc that need to be used in more than one place
|
||||
* (for example, across platforms, or between an item and block).
|
||||
*/
|
||||
public class HexStringKeys {
|
||||
public static final String BRAINSWEPT = "hexcasting:brainswept";
|
||||
}
|
|
@ -2,64 +2,50 @@ package at.petrak.hexcasting.common.misc;
|
|||
|
||||
import at.petrak.hexcasting.common.network.HexMessages;
|
||||
import at.petrak.hexcasting.common.network.MsgBrainsweepAck;
|
||||
import at.petrak.hexcasting.mixin.AccessorLivingEntity;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import at.petrak.hexcasting.xplat.IXplatAbstractions;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.npc.VillagerDataHolder;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraftforge.event.entity.living.LivingConversionEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Brainsweeping {
|
||||
|
||||
public static final String TAG_BRAINSWEPT = "hexcasting:brainswept";
|
||||
|
||||
public static boolean isBrainswept(LivingEntity entity) {
|
||||
return entity instanceof VillagerDataHolder && entity.getPersistentData().getBoolean(TAG_BRAINSWEPT);
|
||||
// Keeping these functions in Brainsweeping just so we have to change less code
|
||||
public static void brainsweep(LivingEntity entity) {
|
||||
IXplatAbstractions.INSTANCE.brainsweep(entity);
|
||||
}
|
||||
|
||||
public static void brainsweep(LivingEntity entity) {
|
||||
if (entity instanceof VillagerDataHolder) {
|
||||
entity.getPersistentData().putBoolean(TAG_BRAINSWEPT, true);
|
||||
|
||||
if (entity instanceof Mob mob)
|
||||
mob.removeFreeWill();
|
||||
|
||||
if (entity instanceof Villager villager) {
|
||||
Brain<Villager> brain = villager.getBrain();
|
||||
if (entity.level instanceof ServerLevel slevel) {
|
||||
brain.stopAll(slevel, villager);
|
||||
}
|
||||
((AccessorLivingEntity) entity).hex$SetBrain(brain.copyWithoutBehaviors());
|
||||
}
|
||||
|
||||
if (entity.level instanceof ServerLevel) {
|
||||
HexMessages.getNetwork().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), MsgBrainsweepAck.of(entity));
|
||||
}
|
||||
}
|
||||
public static boolean isBrainswept(LivingEntity entity) {
|
||||
return IXplatAbstractions.INSTANCE.isBrainswept(entity);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void startTracking(PlayerEvent.StartTracking evt) {
|
||||
Entity target = evt.getTarget();
|
||||
if (evt.getPlayer() instanceof ServerPlayer serverPlayer &&
|
||||
target instanceof VillagerDataHolder && target instanceof LivingEntity living && isBrainswept(living)) {
|
||||
HexMessages.getNetwork().send(PacketDistributor.PLAYER.with(() -> serverPlayer), MsgBrainsweepAck.of(living));
|
||||
target instanceof VillagerDataHolder && target instanceof LivingEntity living && isBrainswept(living)) {
|
||||
HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> serverPlayer), MsgBrainsweepAck.of(living));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void tradeWithVillager(PlayerInteractEvent.EntityInteract evt) {
|
||||
if (evt.getTarget() instanceof Villager v && isBrainswept(v)) {
|
||||
evt.setCanceled(true);
|
||||
public static InteractionResult tradeWithVillager(Player player, Level world, InteractionHand hand, Entity entity,
|
||||
@Nullable EntityHitResult hitResult) {
|
||||
if (entity instanceof Villager v && IXplatAbstractions.INSTANCE.isBrainswept(v)) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
@ -67,7 +53,9 @@ public class Brainsweeping {
|
|||
var outcome = evt.getOutcome();
|
||||
var original = evt.getEntityLiving();
|
||||
if (outcome instanceof VillagerDataHolder && original instanceof VillagerDataHolder) {
|
||||
if (isBrainswept(original)) brainsweep(outcome);
|
||||
if (isBrainswept(original)) {
|
||||
brainsweep(outcome);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
|
||||
import at.petrak.hexcasting.api.player.HexPlayerDataHelper;
|
||||
import at.petrak.hexcasting.client.gui.GuiSpellcasting;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping;
|
||||
import at.petrak.hexcasting.common.particles.ConjureParticleOptions;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
// Ah, java classloading, how I hate thee
|
||||
public record ClientPacketHandler(Object rawMsg) {
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void beep() {
|
||||
if (!(rawMsg instanceof MsgBeepAck msg))
|
||||
return;
|
||||
|
||||
var minecraft = Minecraft.getInstance();
|
||||
var world = minecraft.level;
|
||||
if (world != null){
|
||||
float pitch = (float) Math.pow(2, (msg.note() - 12) / 12.0);
|
||||
world.playLocalSound(msg.target().x, msg.target().y, msg.target().z, msg.instrument().getSoundEvent(), SoundSource.PLAYERS, 3, pitch, false);
|
||||
world.addParticle(ParticleTypes.NOTE, msg.target().x, msg.target().y + 0.2, msg.target().z, msg.note() / 24.0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void blink() {
|
||||
if (!(rawMsg instanceof MsgBlinkAck msg))
|
||||
return;
|
||||
|
||||
var player = Minecraft.getInstance().player;
|
||||
player.setPos(player.position().add(msg.addedPosition()));
|
||||
}
|
||||
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void updateComparator() {
|
||||
if (!(rawMsg instanceof MsgUpdateComparatorVisualsAck msg))
|
||||
return;
|
||||
|
||||
ScryingLensOverlayRegistry.receiveComparatorValue(msg.pos(), msg.value());
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void openSpellGui() {
|
||||
if (!(rawMsg instanceof MsgOpenSpellGuiAck msg))
|
||||
return;
|
||||
|
||||
var mc = Minecraft.getInstance();
|
||||
mc.setScreen(new GuiSpellcasting(msg.hand(), msg.patterns(), msg.components()));
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void brainsweep() {
|
||||
if (!(rawMsg instanceof MsgBrainsweepAck msg))
|
||||
return;
|
||||
|
||||
var level = Minecraft.getInstance().level;
|
||||
if (level != null) {
|
||||
Entity entity = level.getEntity(msg.target());
|
||||
if (entity instanceof LivingEntity living) {
|
||||
Brainsweeping.brainsweep(living);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void newPattern() {
|
||||
if (!(rawMsg instanceof MsgNewSpellPatternAck msg))
|
||||
return;
|
||||
|
||||
var mc = Minecraft.getInstance();
|
||||
if (msg.info().isStackClear()) {
|
||||
// don't pay attention to the screen, so it also stops when we die
|
||||
mc.getSoundManager().stop(HexSounds.CASTING_AMBIANCE.getId(), null);
|
||||
}
|
||||
var screen = Minecraft.getInstance().screen;
|
||||
if (screen instanceof GuiSpellcasting spellGui) {
|
||||
if (msg.info().isStackClear()) {
|
||||
mc.setScreen(null);
|
||||
} else {
|
||||
spellGui.recvServerUpdate(msg.info());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void updateColorizer() {
|
||||
if (!(rawMsg instanceof MsgColorizerUpdateAck msg))
|
||||
return;
|
||||
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player != null) {
|
||||
HexPlayerDataHelper.setColorizer(player, msg.update());
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void updateSentinel() {
|
||||
if (!(rawMsg instanceof MsgSentinelStatusUpdateAck msg))
|
||||
return;
|
||||
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player != null) {
|
||||
HexPlayerDataHelper.setSentinel(player, msg.update());
|
||||
}
|
||||
}
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
// https://math.stackexchange.com/questions/44689/how-to-find-a-random-axis-or-unit-vector-in-3d
|
||||
private static Vec3 randomInCircle(double maxTh) {
|
||||
var th = RANDOM.nextDouble(0.0, maxTh + 0.001);
|
||||
var z = RANDOM.nextDouble(-1.0, 1.0);
|
||||
return new Vec3(Math.sqrt(1.0 - z * z) * Math.cos(th), Math.sqrt(1.0 - z * z) * Math.sin(th), z);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void particleSpray() {
|
||||
if (!(rawMsg instanceof MsgCastParticleAck msg))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < msg.spray().getCount(); i++) {
|
||||
// For the colors, pick any random time to get a mix of colors
|
||||
var color = msg.colorizer().getColor(RANDOM.nextFloat() * 256f, Vec3.ZERO);
|
||||
|
||||
var offset = randomInCircle(Mth.TWO_PI).normalize()
|
||||
.scale(RANDOM.nextFloat() * msg.spray().getSpread() / 2);
|
||||
var pos = msg.spray().getPos().add(offset);
|
||||
|
||||
var phi = Math.acos(1.0 - RANDOM.nextDouble() * (1.0 - Math.cos(msg.spray().getSpread())));
|
||||
var theta = Math.PI * 2.0 * RANDOM.nextDouble();
|
||||
var v = msg.spray().getVel().normalize();
|
||||
// pick any old vector to get a vector normal to v with
|
||||
Vec3 k;
|
||||
if (v.x == 0.0 && v.y == 0.0) {
|
||||
// oops, pick a *different* normal
|
||||
k = new Vec3(1.0, 0.0, 0.0);
|
||||
} else {
|
||||
k = v.cross(new Vec3(0.0, 0.0, 1.0));
|
||||
}
|
||||
var velUnlen = v.scale(Math.cos(phi))
|
||||
.add(k.scale(Math.sin(phi) * Math.cos(theta)))
|
||||
.add(v.cross(k).scale(Math.sin(phi) * Math.sin(theta)));
|
||||
var vel = velUnlen.scale(msg.spray().getVel().length() / 20);
|
||||
|
||||
Minecraft.getInstance().level.addParticle(
|
||||
new ConjureParticleOptions(color, false),
|
||||
pos.x, pos.y, pos.z,
|
||||
vel.x, vel.y, vel.z
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +1,5 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.HexMod;
|
||||
import at.petrak.hexcasting.api.mod.HexApiMessages;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
|
||||
public class HexMessages {
|
||||
private static final String PROTOCOL_VERSION = "1";
|
||||
private static final SimpleChannel NETWORK = NetworkRegistry.newSimpleChannel(
|
||||
new ResourceLocation(HexMod.MOD_ID, "main"),
|
||||
() -> PROTOCOL_VERSION,
|
||||
PROTOCOL_VERSION::equals,
|
||||
PROTOCOL_VERSION::equals
|
||||
);
|
||||
|
||||
public static SimpleChannel getNetwork() {
|
||||
return NETWORK;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
int messageIdx = 0;
|
||||
|
||||
NETWORK.registerMessage(messageIdx++, MsgNewSpellPatternSyn.class, MsgNewSpellPatternSyn::serialize,
|
||||
MsgNewSpellPatternSyn::deserialize, MsgNewSpellPatternSyn::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgNewSpellPatternAck.class, MsgNewSpellPatternAck::serialize,
|
||||
MsgNewSpellPatternAck::deserialize, MsgNewSpellPatternAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgShiftScrollSyn.class, MsgShiftScrollSyn::serialize,
|
||||
MsgShiftScrollSyn::deserialize, MsgShiftScrollSyn::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgBlinkAck.class, MsgBlinkAck::serialize,
|
||||
MsgBlinkAck::deserialize, MsgBlinkAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgSentinelStatusUpdateAck.class, MsgSentinelStatusUpdateAck::serialize,
|
||||
MsgSentinelStatusUpdateAck::deserialize, MsgSentinelStatusUpdateAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgColorizerUpdateAck.class, MsgColorizerUpdateAck::serialize,
|
||||
MsgColorizerUpdateAck::deserialize, MsgColorizerUpdateAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgCastParticleAck.class, MsgCastParticleAck::serialize,
|
||||
MsgCastParticleAck::deserialize, MsgCastParticleAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgOpenSpellGuiAck.class, MsgOpenSpellGuiAck::serialize,
|
||||
MsgOpenSpellGuiAck::deserialize, MsgOpenSpellGuiAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgBeepAck.class, MsgBeepAck::serialize,
|
||||
MsgBeepAck::deserialize, MsgBeepAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgBrainsweepAck.class, MsgBrainsweepAck::serialize,
|
||||
MsgBrainsweepAck::deserialize, MsgBrainsweepAck::handle);
|
||||
NETWORK.registerMessage(messageIdx++, MsgUpdateComparatorVisualsAck.class, MsgUpdateComparatorVisualsAck::serialize,
|
||||
MsgUpdateComparatorVisualsAck::deserialize, MsgUpdateComparatorVisualsAck::handle);
|
||||
|
||||
HexApiMessages.setSyncChannel(NETWORK, MsgSentinelStatusUpdateAck::new, MsgColorizerUpdateAck::new, MsgCastParticleAck::new);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
// https://github.com/VazkiiMods/Botania/blob/1.18.x/Common/src/main/java/vazkii/botania/network/IPacket.java
|
||||
// yoink
|
||||
public interface IMessage {
|
||||
default FriendlyByteBuf toBuf() {
|
||||
var ret = new FriendlyByteBuf(Unpooled.buffer());
|
||||
serialize(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void serialize(FriendlyByteBuf buf);
|
||||
|
||||
/**
|
||||
* Forge auto-assigns incrementing integers, Fabric requires us to declare an ID
|
||||
* These are sent using vanilla's custom plugin channel system and thus are written to every single packet.
|
||||
* So this ID tends to be more terse.
|
||||
*/
|
||||
ResourceLocation getFabricId();
|
||||
}
|
|
@ -1,19 +1,24 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
public record MsgBeepAck(Vec3 target, int note, NoteBlockInstrument instrument) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("beep");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sent server->client to synchronize OpAddMotion when the target is a player.
|
||||
*/
|
||||
public record MsgBeepAck(Vec3 target, int note, NoteBlockInstrument instrument) {
|
||||
public static MsgBeepAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var x = buf.readDouble();
|
||||
|
@ -24,20 +29,29 @@ public record MsgBeepAck(Vec3 target, int note, NoteBlockInstrument instrument)
|
|||
return new MsgBeepAck(new Vec3(x, y, z), note, instrument);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeDouble(this.target.x);
|
||||
buf.writeDouble(this.target.y);
|
||||
buf.writeDouble(this.target.z);
|
||||
buf.writeInt(this.note);
|
||||
buf.writeEnum(instrument);
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::beep);
|
||||
|
||||
public static void handle(MsgBeepAck msg) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
var world = minecraft.level;
|
||||
if (world != null) {
|
||||
float pitch = (float) Math.pow(2, (msg.note() - 12) / 12.0);
|
||||
world.playLocalSound(msg.target().x, msg.target().y, msg.target().z,
|
||||
msg.instrument().getSoundEvent(), SoundSource.PLAYERS, 3, pitch, false);
|
||||
world.addParticle(ParticleTypes.NOTE, msg.target().x, msg.target().y + 0.2, msg.target().z,
|
||||
msg.note() / 24.0, 0, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client to synchronize OpBlink when the target is a player.
|
||||
*/
|
||||
public record MsgBlinkAck(Vec3 addedPosition) {
|
||||
public record MsgBlinkAck(Vec3 addedPosition) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("blink");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgBlinkAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var x = buf.readDouble();
|
||||
|
@ -21,18 +27,20 @@ public record MsgBlinkAck(Vec3 addedPosition) {
|
|||
return new MsgBlinkAck(new Vec3(x, y, z));
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeDouble(this.addedPosition.x);
|
||||
buf.writeDouble(this.addedPosition.y);
|
||||
buf.writeDouble(this.addedPosition.z);
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::blink);
|
||||
public static void handle(MsgBlinkAck self) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var player = Minecraft.getInstance().player;
|
||||
player.setPos(player.position().add(self.addedPosition()));
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,26 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client to synchronize the status of a brainswept mob.
|
||||
*/
|
||||
public record MsgBrainsweepAck(int target) {
|
||||
public record MsgBrainsweepAck(int target) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("sweep");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgBrainsweepAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
|
@ -20,8 +28,8 @@ public record MsgBrainsweepAck(int target) {
|
|||
return new MsgBrainsweepAck(target);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeInt(target);
|
||||
}
|
||||
|
||||
|
@ -29,11 +37,18 @@ public record MsgBrainsweepAck(int target) {
|
|||
return new MsgBrainsweepAck(target.getId());
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::brainsweep);
|
||||
public static void handle(MsgBrainsweepAck msg) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var level = Minecraft.getInstance().level;
|
||||
if (level != null) {
|
||||
Entity entity = level.getEntity(msg.target());
|
||||
if (entity instanceof LivingEntity living) {
|
||||
Brainsweeping.brainsweep(living);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,19 +2,28 @@ package at.petrak.hexcasting.common.network;
|
|||
|
||||
import at.petrak.hexcasting.api.misc.FrozenColorizer;
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray;
|
||||
import at.petrak.hexcasting.common.particles.ConjureParticleOptions;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import java.util.Random;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client to spray particles everywhere.
|
||||
*/
|
||||
public record MsgCastParticleAck(ParticleSpray spray, FrozenColorizer colorizer) {
|
||||
public record MsgCastParticleAck(ParticleSpray spray, FrozenColorizer colorizer) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("cPrtl");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgCastParticleAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
@ -34,8 +43,8 @@ public record MsgCastParticleAck(ParticleSpray spray, FrozenColorizer colorizer)
|
|||
colorizer);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeDouble(this.spray.getPos().x);
|
||||
buf.writeDouble(this.spray.getPos().y);
|
||||
buf.writeDouble(this.spray.getPos().z);
|
||||
|
@ -48,14 +57,51 @@ public record MsgCastParticleAck(ParticleSpray spray, FrozenColorizer colorizer)
|
|||
buf.writeNbt(this.colorizer.serialize());
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::particleSpray);
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
// https://math.stackexchange.com/questions/44689/how-to-find-a-random-axis-or-unit-vector-in-3d
|
||||
private static Vec3 randomInCircle(double maxTh) {
|
||||
var th = RANDOM.nextDouble(0.0, maxTh + 0.001);
|
||||
var z = RANDOM.nextDouble(-1.0, 1.0);
|
||||
return new Vec3(Math.sqrt(1.0 - z * z) * Math.cos(th), Math.sqrt(1.0 - z * z) * Math.sin(th), z);
|
||||
}
|
||||
|
||||
public static void handle(MsgCastParticleAck msg) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < msg.spray().getCount(); i++) {
|
||||
// For the colors, pick any random time to get a mix of colors
|
||||
var color = msg.colorizer().getColor(RANDOM.nextFloat() * 256f, Vec3.ZERO);
|
||||
|
||||
var offset = randomInCircle(Mth.TWO_PI).normalize()
|
||||
.scale(RANDOM.nextFloat() * msg.spray().getSpread() / 2);
|
||||
var pos = msg.spray().getPos().add(offset);
|
||||
|
||||
var phi = Math.acos(1.0 - RANDOM.nextDouble() * (1.0 - Math.cos(msg.spray().getSpread())));
|
||||
var theta = Math.PI * 2.0 * RANDOM.nextDouble();
|
||||
var v = msg.spray().getVel().normalize();
|
||||
// pick any old vector to get a vector normal to v with
|
||||
Vec3 k;
|
||||
if (v.x == 0.0 && v.y == 0.0) {
|
||||
// oops, pick a *different* normal
|
||||
k = new Vec3(1.0, 0.0, 0.0);
|
||||
} else {
|
||||
k = v.cross(new Vec3(0.0, 0.0, 1.0));
|
||||
}
|
||||
var velUnlen = v.scale(Math.cos(phi))
|
||||
.add(k.scale(Math.sin(phi) * Math.cos(theta)))
|
||||
.add(v.cross(k).scale(Math.sin(phi) * Math.sin(theta)));
|
||||
var vel = velUnlen.scale(msg.spray().getVel().length() / 20);
|
||||
|
||||
Minecraft.getInstance().level.addParticle(
|
||||
new ConjureParticleOptions(color, false),
|
||||
pos.x, pos.y, pos.z,
|
||||
vel.x, vel.y, vel.z
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.api.misc.FrozenColorizer;
|
||||
import at.petrak.hexcasting.api.player.HexPlayerDataHelper;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client to synchronize the status of the sentinel.
|
||||
*/
|
||||
public record MsgColorizerUpdateAck(FrozenColorizer update) {
|
||||
public record MsgColorizerUpdateAck(FrozenColorizer update) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("color");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgColorizerUpdateAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
|
@ -21,16 +28,20 @@ public record MsgColorizerUpdateAck(FrozenColorizer update) {
|
|||
return new MsgColorizerUpdateAck(colorizer);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeNbt(this.update.serialize());
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::updateColorizer);
|
||||
public static void handle(MsgColorizerUpdateAck self) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player != null) {
|
||||
HexPlayerDataHelper.setColorizer(player, self.update());
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.ControllerInfo;
|
||||
import at.petrak.hexcasting.client.gui.GuiSpellcasting;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client when the player finishes casting a spell.
|
||||
*/
|
||||
public record MsgNewSpellPatternAck(ControllerInfo info) {
|
||||
public record MsgNewSpellPatternAck(ControllerInfo info) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("patSC");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgNewSpellPatternAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
@ -34,9 +42,8 @@ public record MsgNewSpellPatternAck(ControllerInfo info) {
|
|||
);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(this.info.getWasSpellCast());
|
||||
buf.writeBoolean(this.info.getHasCastingSound());
|
||||
buf.writeBoolean(this.info.isStackClear());
|
||||
|
@ -47,12 +54,24 @@ public record MsgNewSpellPatternAck(ControllerInfo info) {
|
|||
}
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::newPattern);
|
||||
public static void handle(MsgNewSpellPatternAck self) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var mc = Minecraft.getInstance();
|
||||
if (self.info().isStackClear()) {
|
||||
// don't pay attention to the screen, so it also stops when we die
|
||||
mc.getSoundManager().stop(HexSounds.CASTING_AMBIANCE.getId(), null);
|
||||
}
|
||||
var screen = Minecraft.getInstance().screen;
|
||||
if (screen instanceof GuiSpellcasting spellGui) {
|
||||
if (self.info().isStackClear()) {
|
||||
mc.setScreen(null);
|
||||
} else {
|
||||
spellGui.recvServerUpdate(self.info());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,30 +1,41 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.api.mod.HexItemTags;
|
||||
import at.petrak.hexcasting.api.player.HexPlayerDataHelper;
|
||||
import at.petrak.hexcasting.api.spell.casting.ControllerInfo;
|
||||
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
|
||||
import at.petrak.hexcasting.api.spell.casting.ResolvedPatternValidity;
|
||||
import at.petrak.hexcasting.api.spell.math.HexCoord;
|
||||
import at.petrak.hexcasting.api.spell.math.HexPattern;
|
||||
import at.petrak.hexcasting.api.mod.HexItemTags;
|
||||
import at.petrak.hexcasting.common.lib.HexSounds;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent client->server when the player finishes drawing a pattern.
|
||||
* Server will send back a MsgNewSpellPatternAck packet
|
||||
*/
|
||||
public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern, List<ResolvedPattern> resolvedPatterns) {
|
||||
public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern,
|
||||
List<ResolvedPattern> resolvedPatterns)
|
||||
implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("patCS");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgNewSpellPatternSyn deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var hand = buf.readEnum(InteractionHand.class);
|
||||
|
@ -38,8 +49,8 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
|
|||
return new MsgNewSpellPatternSyn(hand, pattern, resolvedPatterns);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeEnum(handUsed);
|
||||
buf.writeNbt(this.pattern.serializeToNBT());
|
||||
buf.writeInt(this.resolvedPatterns.size());
|
||||
|
@ -48,58 +59,56 @@ public record MsgNewSpellPatternSyn(InteractionHand handUsed, HexPattern pattern
|
|||
}
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> networkCtx) {
|
||||
networkCtx.get().enqueueWork(() -> {
|
||||
ServerPlayer sender = networkCtx.get().getSender();
|
||||
if (sender != null) {
|
||||
var held = sender.getItemInHand(this.handUsed);
|
||||
if (held.is(HexItemTags.WANDS)) {
|
||||
boolean autoFail = false;
|
||||
public void handle(MinecraftServer server, ServerPlayer sender) {
|
||||
var held = sender.getItemInHand(this.handUsed);
|
||||
if (held.is(HexItemTags.WANDS)) {
|
||||
boolean autoFail = false;
|
||||
|
||||
if (!resolvedPatterns.isEmpty()) {
|
||||
var allPoints = new ArrayList<HexCoord>();
|
||||
for (int i = 0; i < resolvedPatterns.size() - 1; i++) {
|
||||
ResolvedPattern pat = resolvedPatterns.get(i);
|
||||
allPoints.addAll(pat.getPattern().positions(pat.getOrigin()));
|
||||
}
|
||||
var currentResolvedPattern = resolvedPatterns.get(resolvedPatterns.size() - 1);
|
||||
var currentSpellPoints = currentResolvedPattern.getPattern().positions(currentResolvedPattern.getOrigin());
|
||||
if (currentSpellPoints.stream().anyMatch(allPoints::contains))
|
||||
autoFail = true;
|
||||
}
|
||||
|
||||
var harness = HexPlayerDataHelper.getHarness(sender, this.handUsed);
|
||||
|
||||
ControllerInfo clientInfo;
|
||||
if (autoFail) {
|
||||
clientInfo = new ControllerInfo(false, false, harness.getStack().isEmpty(), true, harness.generateDescs());
|
||||
} else {
|
||||
clientInfo = harness.executeNewPattern(this.pattern, sender.getLevel());
|
||||
|
||||
if (clientInfo.getWasSpellCast() && clientInfo.getHasCastingSound()) {
|
||||
sender.level.playSound(null, sender.getX(), sender.getY(), sender.getZ(),
|
||||
HexSounds.ACTUALLY_CAST.get(), SoundSource.PLAYERS, 1f,
|
||||
1f + ((float) Math.random() - 0.5f) * 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
if (clientInfo.isStackClear()) {
|
||||
HexPlayerDataHelper.setHarness(sender, null);
|
||||
HexPlayerDataHelper.setPatterns(sender, List.of());
|
||||
} else {
|
||||
HexPlayerDataHelper.setHarness(sender, harness);
|
||||
if (!resolvedPatterns.isEmpty())
|
||||
resolvedPatterns.get(resolvedPatterns.size() - 1).setValid(clientInfo.getWasPrevPatternInvalid() ?
|
||||
ResolvedPatternValidity.ERROR : ResolvedPatternValidity.OK);
|
||||
HexPlayerDataHelper.setPatterns(sender, resolvedPatterns);
|
||||
}
|
||||
|
||||
HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> sender), new MsgNewSpellPatternAck(clientInfo));
|
||||
if (!resolvedPatterns.isEmpty()) {
|
||||
var allPoints = new ArrayList<HexCoord>();
|
||||
for (int i = 0; i < resolvedPatterns.size() - 1; i++) {
|
||||
ResolvedPattern pat = resolvedPatterns.get(i);
|
||||
allPoints.addAll(pat.getPattern().positions(pat.getOrigin()));
|
||||
}
|
||||
var currentResolvedPattern = resolvedPatterns.get(resolvedPatterns.size() - 1);
|
||||
var currentSpellPoints = currentResolvedPattern.getPattern()
|
||||
.positions(currentResolvedPattern.getOrigin());
|
||||
if (currentSpellPoints.stream().anyMatch(allPoints::contains)) {
|
||||
autoFail = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
networkCtx.get().setPacketHandled(true);
|
||||
|
||||
var harness = HexPlayerDataHelper.getHarness(sender, this.handUsed);
|
||||
|
||||
ControllerInfo clientInfo;
|
||||
if (autoFail) {
|
||||
clientInfo = new ControllerInfo(false, false, harness.getStack().isEmpty(), true,
|
||||
harness.generateDescs());
|
||||
} else {
|
||||
clientInfo = harness.executeNewPattern(this.pattern, sender.getLevel());
|
||||
|
||||
if (clientInfo.getWasSpellCast() && clientInfo.getHasCastingSound()) {
|
||||
sender.level.playSound(null, sender.getX(), sender.getY(), sender.getZ(),
|
||||
HexSounds.ACTUALLY_CAST.get(), SoundSource.PLAYERS, 1f,
|
||||
1f + ((float) Math.random() - 0.5f) * 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
if (clientInfo.isStackClear()) {
|
||||
HexPlayerDataHelper.setHarness(sender, null);
|
||||
HexPlayerDataHelper.setPatterns(sender, List.of());
|
||||
} else {
|
||||
HexPlayerDataHelper.setHarness(sender, harness);
|
||||
if (!resolvedPatterns.isEmpty()) {
|
||||
resolvedPatterns.get(resolvedPatterns.size() - 1).setValid(clientInfo.getWasPrevPatternInvalid() ?
|
||||
ResolvedPatternValidity.ERROR : ResolvedPatternValidity.OK);
|
||||
}
|
||||
HexPlayerDataHelper.setPatterns(sender, resolvedPatterns);
|
||||
}
|
||||
|
||||
HexMessages.getNetwork()
|
||||
.send(PacketDistributor.PLAYER.with(() -> sender), new MsgNewSpellPatternAck(clientInfo));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,22 +1,30 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.ResolvedPattern;
|
||||
import at.petrak.hexcasting.client.gui.GuiSpellcasting;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client when the player opens the spell gui to request the server provide the current stack.
|
||||
*/
|
||||
public record MsgOpenSpellGuiAck(InteractionHand hand, List<ResolvedPattern> patterns, List<Component> components) {
|
||||
public record MsgOpenSpellGuiAck(InteractionHand hand, List<ResolvedPattern> patterns, List<Component> components)
|
||||
implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("cGui");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgOpenSpellGuiAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
@ -38,9 +46,7 @@ public record MsgOpenSpellGuiAck(InteractionHand hand, List<ResolvedPattern> pat
|
|||
return new MsgOpenSpellGuiAck(hand, patterns, desc);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeEnum(this.hand);
|
||||
|
||||
buf.writeInt(this.patterns.size());
|
||||
|
@ -54,12 +60,13 @@ public record MsgOpenSpellGuiAck(InteractionHand hand, List<ResolvedPattern> pat
|
|||
}
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::openSpellGui);
|
||||
public static void handle(MsgOpenSpellGuiAck msg) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var mc = Minecraft.getInstance();
|
||||
mc.setScreen(new GuiSpellcasting(msg.hand(), msg.patterns(), msg.components()));
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.api.player.HexPlayerDataHelper;
|
||||
import at.petrak.hexcasting.api.player.Sentinel;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client to synchronize the status of the sentinel.
|
||||
*/
|
||||
public record MsgSentinelStatusUpdateAck(Sentinel update) {
|
||||
public record MsgSentinelStatusUpdateAck(Sentinel update) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("sntnl");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgSentinelStatusUpdateAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
|
@ -28,8 +35,7 @@ public record MsgSentinelStatusUpdateAck(Sentinel update) {
|
|||
return new MsgSentinelStatusUpdateAck(sentinel);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeBoolean(update.hasSentinel());
|
||||
buf.writeBoolean(update.extendsRange());
|
||||
buf.writeDouble(update.position().x);
|
||||
|
@ -38,11 +44,15 @@ public record MsgSentinelStatusUpdateAck(Sentinel update) {
|
|||
buf.writeResourceLocation(update.dimension().location());
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::updateSentinel);
|
||||
public static void handle(MsgSentinelStatusUpdateAck self) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player != null) {
|
||||
HexPlayerDataHelper.setSentinel(player, self.update());
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,19 +11,27 @@ import net.minecraft.network.FriendlyByteBuf;
|
|||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent client->server when the client shift+scrolls with a shift-scrollable item
|
||||
* or scrolls in the spellcasting UI.
|
||||
*/
|
||||
public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolean isCtrl) {
|
||||
public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolean isCtrl) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("scroll");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgShiftScrollSyn deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var hand = buf.readEnum(InteractionHand.class);
|
||||
|
@ -32,27 +40,20 @@ public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolea
|
|||
return new MsgShiftScrollSyn(hand, scrollDelta, isCtrl);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeEnum(this.hand);
|
||||
buf.writeDouble(this.scrollDelta);
|
||||
buf.writeBoolean(this.isCtrl);
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ServerPlayer sender = ctx.get().getSender();
|
||||
if (sender != null) {
|
||||
var stack = sender.getItemInHand(hand);
|
||||
public void handle(MinecraftServer server, ServerPlayer sender) {
|
||||
var stack = sender.getItemInHand(hand);
|
||||
|
||||
if (stack.getItem() == HexItems.SPELLBOOK.get()) {
|
||||
spellbook(sender, stack);
|
||||
} else if (stack.getItem() == HexItems.ABACUS.get()) {
|
||||
abacus(sender, stack);
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
if (stack.getItem() == HexItems.SPELLBOOK.get()) {
|
||||
spellbook(sender, stack);
|
||||
} else if (stack.getItem() == HexItems.ABACUS.get()) {
|
||||
abacus(sender, stack);
|
||||
}
|
||||
}
|
||||
|
||||
private void spellbook(ServerPlayer sender, ItemStack stack) {
|
||||
|
@ -66,28 +67,32 @@ public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolea
|
|||
|
||||
MutableComponent component;
|
||||
if (hand == InteractionHand.OFF_HAND && stack.hasCustomHoverName()) {
|
||||
if (sealed)
|
||||
if (sealed) {
|
||||
component = new TranslatableComponent("hexcasting.tooltip.spellbook.page_with_name.sealed",
|
||||
new TextComponent(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent(String.valueOf(len)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent("").withStyle(stack.getRarity().color, ChatFormatting.ITALIC).append(stack.getHoverName()),
|
||||
new TextComponent(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent(String.valueOf(len)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent("").withStyle(stack.getRarity().color, ChatFormatting.ITALIC)
|
||||
.append(stack.getHoverName()),
|
||||
new TranslatableComponent("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD));
|
||||
else
|
||||
} else {
|
||||
component = new TranslatableComponent("hexcasting.tooltip.spellbook.page_with_name",
|
||||
new TextComponent(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent(String.valueOf(len)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent("").withStyle(stack.getRarity().color, ChatFormatting.ITALIC).append(stack.getHoverName()));
|
||||
new TextComponent("").withStyle(stack.getRarity().color, ChatFormatting.ITALIC)
|
||||
.append(stack.getHoverName()));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (sealed)
|
||||
if (sealed) {
|
||||
component = new TranslatableComponent("hexcasting.tooltip.spellbook.page.sealed",
|
||||
new TextComponent(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent(String.valueOf(len)).withStyle(ChatFormatting.WHITE),
|
||||
new TranslatableComponent("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD));
|
||||
else
|
||||
} else {
|
||||
component = new TranslatableComponent("hexcasting.tooltip.spellbook.page",
|
||||
new TextComponent(String.valueOf(newIdx)).withStyle(ChatFormatting.WHITE),
|
||||
new TextComponent(String.valueOf(len)).withStyle(ChatFormatting.WHITE));
|
||||
}
|
||||
}
|
||||
|
||||
sender.displayClientMessage(component.withStyle(ChatFormatting.GRAY), true);
|
||||
|
@ -122,7 +127,8 @@ public record MsgShiftScrollSyn(InteractionHand hand, double scrollDelta, boolea
|
|||
var datumTag = HexItems.ABACUS.get().readDatumTag(stack);
|
||||
if (datumTag != null) {
|
||||
var popup = SpellDatum.DisplayFromTag(datumTag);
|
||||
sender.displayClientMessage(new TranslatableComponent("hexcasting.tooltip.abacus", popup).withStyle(ChatFormatting.GREEN), true);
|
||||
sender.displayClientMessage(
|
||||
new TranslatableComponent("hexcasting.tooltip.abacus", popup).withStyle(ChatFormatting.GREEN), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
package at.petrak.hexcasting.common.network;
|
||||
|
||||
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Sent server->client when a player is looking at a block through a lens whose comparator value is not the same as what they last saw.
|
||||
*/
|
||||
public record MsgUpdateComparatorVisualsAck(BlockPos pos, int value) {
|
||||
public record MsgUpdateComparatorVisualsAck(BlockPos pos, int value) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("cmp");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgUpdateComparatorVisualsAck deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
@ -23,21 +29,20 @@ public record MsgUpdateComparatorVisualsAck(BlockPos pos, int value) {
|
|||
return new MsgUpdateComparatorVisualsAck(pos, value);
|
||||
}
|
||||
|
||||
public void serialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeInt(this.value);
|
||||
if (this.value != -1) {
|
||||
buf.writeBlockPos(this.pos);
|
||||
}
|
||||
}
|
||||
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientPacketHandler handler = new ClientPacketHandler(this);
|
||||
DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> handler::updateComparator);
|
||||
public static void handle(MsgUpdateComparatorVisualsAck msg) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ScryingLensOverlayRegistry.receiveComparatorValue(msg.pos(), msg.value());
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,11 @@ package at.petrak.hexcasting.xplat;
|
|||
|
||||
import at.petrak.hexcasting.api.HexAPI;
|
||||
import at.petrak.hexcasting.common.command.PatternResLocArgument;
|
||||
import at.petrak.hexcasting.common.network.IMessage;
|
||||
import net.minecraft.commands.synchronization.ArgumentTypes;
|
||||
import net.minecraft.commands.synchronization.EmptyArgumentSerializer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -13,6 +16,14 @@ public interface IXplatAbstractions {
|
|||
|
||||
boolean isPhysicalClient();
|
||||
|
||||
void brainsweep(LivingEntity e);
|
||||
|
||||
boolean isBrainswept(LivingEntity e);
|
||||
|
||||
void sendPacketToPlayer(ServerPlayer target, IMessage packet);
|
||||
|
||||
void sendPacketToServer(IMessage packet);
|
||||
|
||||
default void init() {
|
||||
HexAPI.LOGGER.info("Hello Hexcasting! This is {}!", this.platform());
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package at.petrak.hexcasting.fabric.network;
|
||||
|
||||
public class FabricPacketHandler {
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package at.petrak.hexcasting.fabric.xplat;
|
||||
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping;
|
||||
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
|
||||
|
||||
public class FabricListenersSetup {
|
||||
public static void init() {
|
||||
UseEntityCallback.EVENT.register(Brainsweeping::tradeWithVillager);
|
||||
}
|
||||
}
|
|
@ -4,33 +4,12 @@ import at.petrak.hexcasting.api.HexAPI
|
|||
import at.petrak.hexcasting.api.PatternRegistry
|
||||
import at.petrak.hexcasting.api.advancements.HexAdvancementTriggers
|
||||
import at.petrak.hexcasting.api.mod.HexConfig
|
||||
import at.petrak.hexcasting.api.mod.HexStatistics
|
||||
import at.petrak.hexcasting.api.player.HexPlayerDataHelper
|
||||
import at.petrak.hexcasting.client.*
|
||||
import at.petrak.hexcasting.common.blocks.HexBlockEntities
|
||||
import at.petrak.hexcasting.common.blocks.HexBlocks
|
||||
import at.petrak.hexcasting.common.casting.RegisterPatterns
|
||||
import at.petrak.hexcasting.common.casting.operators.spells.great.OpFlight
|
||||
import at.petrak.hexcasting.common.command.HexCommands
|
||||
import at.petrak.hexcasting.common.entities.HexEntities
|
||||
import at.petrak.hexcasting.common.items.HexItems
|
||||
import at.petrak.hexcasting.common.lib.HexCapabilityHandler
|
||||
import at.petrak.hexcasting.common.lib.HexSounds
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping
|
||||
import at.petrak.hexcasting.common.network.HexMessages
|
||||
import at.petrak.hexcasting.common.particles.HexParticles
|
||||
import at.petrak.hexcasting.common.recipe.HexComposting
|
||||
import at.petrak.hexcasting.common.recipe.HexCustomRecipes
|
||||
import at.petrak.hexcasting.common.recipe.HexRecipeSerializers
|
||||
import at.petrak.hexcasting.datagen.HexDataGenerators
|
||||
import at.petrak.hexcasting.datagen.lootmods.HexLootModifiers
|
||||
import at.petrak.hexcasting.forge.ForgeHexConfig
|
||||
import at.petrak.hexcasting.server.TickScheduler
|
||||
import at.petrak.hexcasting.forge.network.ForgePacketHandler
|
||||
import at.petrak.hexcasting.forge.xplat.ForgeListenersSetup
|
||||
import at.petrak.hexcasting.xplat.IXplatAbstractions
|
||||
import net.minecraftforge.api.distmarker.Dist
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.DistExecutor
|
||||
import net.minecraftforge.fml.ModLoadingContext
|
||||
import net.minecraftforge.fml.common.Mod
|
||||
import net.minecraftforge.fml.config.ModConfig
|
||||
|
@ -56,6 +35,15 @@ object HexMod {
|
|||
HexConfig.setCommon(config.left)
|
||||
HexConfig.setClient(clientConfig.left)
|
||||
HexConfig.setServer(serverConfig.left)
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, config.right)
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, serverConfig.right)
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, clientConfig.right)
|
||||
|
||||
|
||||
ForgeListenersSetup.init()
|
||||
ForgePacketHandler.init()
|
||||
|
||||
/*
|
||||
|
||||
// mod lifecycle
|
||||
val modBus = thedarkcolour.kotlinforforge.forge.MOD_BUS
|
||||
|
@ -98,12 +86,7 @@ object HexMod {
|
|||
}
|
||||
}
|
||||
|
||||
// and then things that don't require busses
|
||||
HexMessages.register()
|
||||
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, config.right)
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, serverConfig.right)
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, clientConfig.right)
|
||||
*/
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package at.petrak.hexcasting.forge.network;
|
||||
|
||||
import at.petrak.hexcasting.HexMod;
|
||||
import at.petrak.hexcasting.common.network.*;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
import org.apache.logging.log4j.util.TriConsumer;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ForgePacketHandler {
|
||||
private static final String PROTOCOL_VERSION = "1";
|
||||
private static final SimpleChannel NETWORK = NetworkRegistry.newSimpleChannel(
|
||||
new ResourceLocation(HexMod.MOD_ID, "main"),
|
||||
() -> PROTOCOL_VERSION,
|
||||
PROTOCOL_VERSION::equals,
|
||||
PROTOCOL_VERSION::equals
|
||||
);
|
||||
|
||||
public static SimpleChannel getNetwork() {
|
||||
return NETWORK;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
int messageIdx = 0;
|
||||
|
||||
// Client -> server
|
||||
NETWORK.registerMessage(messageIdx++, MsgNewSpellPatternSyn.class, MsgNewSpellPatternSyn::serialize,
|
||||
MsgNewSpellPatternSyn::deserialize, makeServerBoundHandler(MsgNewSpellPatternSyn::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgShiftScrollSyn.class, MsgShiftScrollSyn::serialize,
|
||||
MsgShiftScrollSyn::deserialize, makeServerBoundHandler(MsgShiftScrollSyn::handle));
|
||||
|
||||
// Server -> client
|
||||
NETWORK.registerMessage(messageIdx++, MsgNewSpellPatternAck.class, MsgNewSpellPatternAck::serialize,
|
||||
MsgNewSpellPatternAck::deserialize, makeClientBoundHandler(MsgNewSpellPatternAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgBlinkAck.class, MsgBlinkAck::serialize,
|
||||
MsgBlinkAck::deserialize, makeClientBoundHandler(MsgBlinkAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgSentinelStatusUpdateAck.class, MsgSentinelStatusUpdateAck::serialize,
|
||||
MsgSentinelStatusUpdateAck::deserialize, makeClientBoundHandler(MsgSentinelStatusUpdateAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgColorizerUpdateAck.class, MsgColorizerUpdateAck::serialize,
|
||||
MsgColorizerUpdateAck::deserialize, makeClientBoundHandler(MsgColorizerUpdateAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgCastParticleAck.class, MsgCastParticleAck::serialize,
|
||||
MsgCastParticleAck::deserialize, makeClientBoundHandler(MsgCastParticleAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgOpenSpellGuiAck.class, MsgOpenSpellGuiAck::serialize,
|
||||
MsgOpenSpellGuiAck::deserialize, makeClientBoundHandler(MsgOpenSpellGuiAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgBeepAck.class, MsgBeepAck::serialize,
|
||||
MsgBeepAck::deserialize, makeClientBoundHandler(MsgBeepAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgBrainsweepAck.class, MsgBrainsweepAck::serialize,
|
||||
MsgBrainsweepAck::deserialize, makeClientBoundHandler(MsgBrainsweepAck::handle));
|
||||
NETWORK.registerMessage(messageIdx++, MsgUpdateComparatorVisualsAck.class,
|
||||
MsgUpdateComparatorVisualsAck::serialize,
|
||||
MsgUpdateComparatorVisualsAck::deserialize,
|
||||
makeClientBoundHandler(MsgUpdateComparatorVisualsAck::handle));
|
||||
}
|
||||
|
||||
private static <T> BiConsumer<T, Supplier<NetworkEvent.Context>> makeServerBoundHandler(
|
||||
TriConsumer<T, MinecraftServer, ServerPlayer> handler) {
|
||||
return (m, ctx) -> {
|
||||
handler.accept(m, ctx.get().getSender().getServer(), ctx.get().getSender());
|
||||
ctx.get().setPacketHandled(true);
|
||||
};
|
||||
}
|
||||
|
||||
private static <T> BiConsumer<T, Supplier<NetworkEvent.Context>> makeClientBoundHandler(Consumer<T> consumer) {
|
||||
return (m, ctx) -> {
|
||||
consumer.accept(m);
|
||||
ctx.get().setPacketHandled(true);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package at.petrak.hexcasting.forge.xplat;
|
||||
|
||||
import at.petrak.hexcasting.common.misc.Brainsweeping;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
|
||||
public class ForgeListenersSetup {
|
||||
public static void init() {
|
||||
var evBus = MinecraftForge.EVENT_BUS;
|
||||
|
||||
evBus.addListener((PlayerInteractEvent.EntityInteract evt) -> {
|
||||
var res = Brainsweeping.tradeWithVillager(evt.getPlayer(), evt.getWorld(), evt.getHand(), evt.getTarget(),
|
||||
null);
|
||||
if (res.consumesAction()) {
|
||||
evt.setCanceled(true);
|
||||
evt.setCancellationResult(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,9 +1,22 @@
|
|||
package at.petrak.hexcasting.forge.xplat;
|
||||
|
||||
import at.petrak.hexcasting.common.lib.HexStringKeys;
|
||||
import at.petrak.hexcasting.common.network.IMessage;
|
||||
import at.petrak.hexcasting.common.network.MsgBrainsweepAck;
|
||||
import at.petrak.hexcasting.forge.network.ForgePacketHandler;
|
||||
import at.petrak.hexcasting.mixin.AccessorLivingEntity;
|
||||
import at.petrak.hexcasting.xplat.IXplatAbstractions;
|
||||
import at.petrak.hexcasting.xplat.Platform;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.npc.VillagerDataHolder;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class ForgeXplatImpl implements IXplatAbstractions {
|
||||
@Override
|
||||
|
@ -15,4 +28,43 @@ public class ForgeXplatImpl implements IXplatAbstractions {
|
|||
public boolean isPhysicalClient() {
|
||||
return FMLLoader.getDist() == Dist.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void brainsweep(LivingEntity entity) {
|
||||
if (entity instanceof VillagerDataHolder) {
|
||||
entity.getPersistentData().putBoolean(HexStringKeys.BRAINSWEPT, true);
|
||||
|
||||
if (entity instanceof Mob mob) {
|
||||
mob.removeFreeWill();
|
||||
}
|
||||
|
||||
if (entity instanceof Villager villager) {
|
||||
Brain<Villager> brain = villager.getBrain();
|
||||
if (entity.level instanceof ServerLevel slevel) {
|
||||
brain.stopAll(slevel, villager);
|
||||
}
|
||||
((AccessorLivingEntity) entity).hex$SetBrain(brain.copyWithoutBehaviors());
|
||||
}
|
||||
|
||||
if (entity.level instanceof ServerLevel) {
|
||||
ForgePacketHandler.getNetwork()
|
||||
.send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), MsgBrainsweepAck.of(entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBrainswept(LivingEntity e) {
|
||||
return e instanceof VillagerDataHolder && e.getPersistentData().getBoolean(HexStringKeys.BRAINSWEPT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacketToPlayer(ServerPlayer target, IMessage packet) {
|
||||
ForgePacketHandler.getNetwork().send(PacketDistributor.PLAYER.with(() -> target), packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacketToServer(IMessage packet) {
|
||||
ForgePacketHandler.getNetwork().sendToServer(packet);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue