Jump to content

Recommended Posts

Posted (edited)

So here is a relatively dumb question I am sure. I have multiple capabilities. 3 at the moment but only 2 are actually registered and being used the 3rd is completely disabled and not even registered as I am still working on it. When the time comes I want to Register correctly. As it is set-up now, each capability has an event handler (the stupid part that is probably wrong).

 

In each capabilities' EventHandler has the particular effects that I want that Capability to work with. So the AttachingEvent, an onDeath, and onAttack etc. However, I am noticing conflicts. I am getting crashes and it would seem that one Capability is trying to cast to another Capability despite there being ZERO like absolute ZERO reference to it anywhere in my code. This tells me that I am likely being foolish, and there should only be one Event handler that attaches all the capabilities at once and therefore only one 

MinecraftForge.EVENT_BUS.addListener(CAPABILITY HANDLER CLASS HERE::onAttachCapabilitiesEvent);
MinecraftForge.EVENT_BUS.addListener(CAPABILITY HANDLER CLASS HERE::onAttackEvent);

etc., etc. 

 

Here is the crash report. The reason why I know it isn't in that EffectRemeberance class is because once I disable my Explosium capability that for whatever reason is trying to cast itself everywhere the code works just fine, perfectly actually, (even my debug messages) and there is no issue. So this tells me I am doing something wrong when registering, and the only thing that "looks" off to me is all the separate registering I am doing and separate event handlers. 

 

If you need to see the Main where all the registering is happening here it is. It is currently a mess because I haven't cleaned and optimized it just yet: https://pastebin.com/YWKvtbdK

Edited by HalestormXV
Posted

Don't register a capability with the event system, make a single class that handles ALL your events and then get the capability from the relevant object given to you by the event data.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)
1 hour ago, Draco18s said:

Don't register a capability with the event system, make a single class that handles ALL your events and then get the capability from the relevant object given to you by the event data.

Okay that can be done, so I just converted to the the above as you said. Everything is still working fine and my two capabilities are now registered in a CapabilityRegistration class and there is now a single CapabilityEventHandler class (so far with only onDeath subscribed to and onAttack subscribed to) but I am still getting the same error where it seems that the first capability to register is trying to cast to the other and as stated above, they dont even so much as reference each other anywhere in my code. And I am using the event to pull the data and check ifPresent. And as you will see below the Location Capability isn't even mentioned in here nor is it referenced.

 

public class CapabilityEventHandler {

    @SubscribeEvent
    public void onDeathEvent(LivingDeathEvent event) {
        Entity entity = event.getEntity();
        entity.getCapability(CapabilityEntityExplosium.ENTITY_EXPLOSIUM_CAPABILITY).ifPresent(h -> {
            int count = h.getCount();
            if (count > 0) {
                entity.getEntityWorld().createExplosion(entity, entity.getPosX(), entity.getPosY(), entity.getPosZ(), count * .3f + 1.0f, Explosion.Mode.DESTROY);
            }
        });
    }

    @SubscribeEvent
    public void onAttackEvent(AttackEntityEvent event) {
        Entity attacker = event.getEntity();
        if (attacker instanceof PlayerEntity){
            PlayerEntity player = (PlayerEntity) attacker;
            ItemStack stack = player.getHeldItemMainhand();
            if (stack.getItem() == ItemInitDeferred.EXPLOSIUM_DUST.get()) {
                Entity target = event.getTarget();
                target.getCapability(CapabilityEntityExplosium.ENTITY_EXPLOSIUM_CAPABILITY).ifPresent(handle ->
                {
                    int count = handle.getCount() + 1;
                    if (count < 9) {
                        handle.setCount(count);
                        player.sendStatusMessage(new TranslationTextComponent("message.increase_count", Integer.toString(count)), true);
                        stack.shrink(1);
                        player.setHeldItem(Hand.MAIN_HAND, stack);
                        event.setCanceled(true);
                        target.getEntityWorld().addParticle(ParticleTypes.FIREWORK, target.getPosX(), target.getPosY() + 1, target.getPosZ(), 0.0, 0.0, 0.0);
                    }else{
                        player.sendStatusMessage(new TranslationTextComponent("message.at_max_count", Integer.toString(count-1)), true);
                        event.setCanceled(true);
                    }
                });
            }
        }
    }
}
Edited by HalestormXV
Posted

I don't know if you had noticed but I don't think this is where crash occurred.

  1. java.lang.ClassCastException: com.halestormxv.mysterium.data.explosium.DefaultEntityExplosium cannot be cast to com.halestormxv.mysterium.data.location.IEntityLocation
  2.     at net.minecraftforge.common.util.LazyOptional.ifPresent(LazyOptional.java:161) ~[?:?] {re:classloading}
  3.     at com.halestormxv.mysterium.effects.EffectRemembrance.savePosition(EffectRemembrance.java:91) ~[?:?] {re:classloading}
Posted (edited)

The crash seems to be occurring somewhere in my (now) CapabilityEvent Handler. It is being triggered (the crash) when an Entity either getsAttacked or onDeath. For whatever reason my two capabilities seem to be conflicting. My ExplosiumCapability which is the only one that uses the attacked and onDeath, and my Location capability. The location capability is registered first in the MainClass, I took it off the Event_Bus.addListener like Draco suggested, and simply just now call a .register(CapabilityRegistration.class) it didn't make a difference.

 

For whatever reason whichever capability is registered first (now the location one) tries to cast itself to the capability registered second (now the explosium one) . My confusion is why. They in no way reference each other. the attack and the onDeath events don't even look for let alone pull data from anything except the Explosium capability as it should be. 

 

I know the code is somewhat correct, because if I disable the Explosium capability the Location one works just fine and does everything it is supposed to do. And if I disable the location capability the Explosium one works just fine and doesnt crash or anything and does exactly what it is supposed to. Which leads me back to my original point which is something is getting messed up perhaps when they registered?

Edited by HalestormXV
Posted

Show your capability registration.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
private void setup(final FMLCommonSetupEvent event)
{
    //CapabilityEntityLocation.register(); <---Disabled to make sure that they work when one is disabled and the other is enabled
    CapabilityEntityExplosium.register(); *****

    ComposterBlock.registerCompostable(0.7f, BlockInitDeferred.ARCANUM_LEAVES.get());
    DeferredWorkQueue.runLater(StructureGen::generateStructures);
    registerEntityWorldSpawns(ModEntityTypes.MOOPLE_ENTITY.get(), 89, 2, 4, BiomeInit.THE_MYSTIC_HILLS.get());
    registerEntityWorldSpawns(ModEntityTypes.NOVICE_CULTIST.get(), 72, 1, 4, BiomeInit.THE_LARVEN_FLATS.get(), BiomeInit.THE_MYSTIC_HILLS.get());
    PotionInit.addBrewingRecipes();
    MinecraftForge.EVENT_BUS.register(CapabilityRegistration.class); ********
    MinecraftForge.EVENT_BUS.addListener(WatchfulEyeBreakEvent::breakUnderWatch);
    MinecraftForge.EVENT_BUS.addListener(ChangedMagicTools::unequippedMagicTool);
    MinecraftForge.EVENT_BUS.register(CapabilityEventHandler.class);
}

Segment of Main ^

 

public class CapabilityRegistration {
    private static final ResourceLocation ENTITY_LOCATION_CAPABILITY = new ResourceLocation(MysteriumMain.MOD_ID, "locdata");
    private static final ResourceLocation ENTITY_EXPLOSIUM_CAPABILITY = new ResourceLocation(MysteriumMain.MOD_ID, "count");

    @SubscribeEvent
    public static void attachCapability(AttachCapabilitiesEvent<Entity> event){
        Entity entity = event.getObject();
        if (entity instanceof LivingEntity) {
            //event.addCapability(ENTITY_LOCATION_CAPABILITY, new EntityLocationProvider());
            event.addCapability(ENTITY_EXPLOSIUM_CAPABILITY, new EntityExplosiumProvider());
        }
    }
}

CapabilityRegistration/Attachment ^

 

public class CapabilityEntityLocation {
    @CapabilityInject(IEntityLocation.class)
    public static Capability<IEntityLocation> ENTITY_LOCATION_CAPABILITY = null;

    public static void register() {
        CapabilityManager.INSTANCE.register(IEntityLocation.class, new Storage(), DefaultEntityLocation::new);
    }

    public static class Storage implements Capability.IStorage<IEntityLocation> {

        @Nullable
        @Override
        public INBT writeNBT(Capability<IEntityLocation> capability, IEntityLocation instance, Direction side) {
            CompoundNBT tag = new CompoundNBT();
            tag.putDouble("xLoc", instance.getX());
            tag.putDouble("yLoc", instance.getY());
            tag.putDouble("zLoc", instance.getZ());
            tag.putInt("dimID", instance.getDimId());
            return tag;
        }

        @Override
        public void readNBT(Capability<IEntityLocation> capability, IEntityLocation instance, Direction side, INBT nbt) {
            double xLoc = ((CompoundNBT) nbt).getDouble("xLoc");
            double yLoc = ((CompoundNBT) nbt).getDouble("yLoc");
            double zLoc = ((CompoundNBT) nbt).getDouble("zLoc");
            int dimID = ((CompoundNBT) nbt).getInt("dimID");
            instance.setX(xLoc);
            instance.setY(yLoc);
            instance.setZ(zLoc);
            instance.setDim(dimID);
        }
    }
}

Initializing and Injecting the LocationCapability ^ (currently disabled in main)

 

public class CapabilityEntityExplosium {
    @CapabilityInject(IEntityExplosium.class)
    public static Capability<IEntityExplosium> ENTITY_EXPLOSIUM_CAPABILITY = null;

    public static void register() {
        CapabilityManager.INSTANCE.register(IEntityExplosium.class, new Storage(), DefaultEntityExplosium::new);
    }

    public static class Storage implements Capability.IStorage<IEntityExplosium> {

        @Nullable
        @Override
        public INBT writeNBT(Capability<IEntityExplosium> capability, IEntityExplosium instance, Direction side) {
            CompoundNBT tag = new CompoundNBT();
            tag.putInt("count", instance.getCount());
            return tag;
        }

        @Override
        public void readNBT(Capability<IEntityExplosium> capability, IEntityExplosium instance, Direction side, INBT nbt) {
            int count = ((CompoundNBT) nbt).getInt("count");
            instance.setCount(count);
        }
    }
}

Initlizing and Injecting the Explosium one ^ (currently is working with the disabling of the location one)

Posted (edited)

Just giving this a bump as I solved it. @Draco18s thanks for the pointers and tips. I see why they were trying to cast to each other. My Provider, for each Capability never actually checked to ensure that the Capability was in fact the Capability it has to cast to.

 

I am guessing it has something to do with Lazy (i am very new to Lazy to be quite honest so it doesnt surprise me that my error was in there).

 

For reference I built my Capability system similar to how McJty built his in the tutorial videos for 1.15.2 and also took bigger aspects like registration and what not from TheGreyGhost. After looking at TheGreyGhosts capability code as a whole (https://github.com/TheGreyGhost/MinecraftByExample/tree/1-15-2-working/src/main/java/minecraftbyexample/mbe65_capability) I see that he actually enforces a check in his providers, the step I missed above. Which would make sense why when one was disabled it wouldn't conflict because there wasn't anything to conflict with when setting up the getCapability. 

 

My question now, because as I have repeatedly said, I am not just in it for answers, i want to actually learn the workings of it because that makes you a better coder and helps enhance your coding knowledge, is WHY that check is needed? If these are entirely separate classes that don't even reference/link to each other, why does that check still need to be made. Does it in fact have to do with how Lazy works?

Edited by HalestormXV
Posted
43 minutes ago, HalestormXV said:

Does it in fact have to do with how Lazy works?

No, it has to do with how anything works. Imagine you were trying to cast an instance of Object A to Object B (let's say Object A is LivingEntity and Object B is PlayerEntity). We cannot blindly cast one to the other as not all LivingEntities are PlayerEntities. Therefore, we have to insure that the entity is a player before casting using some sort of check. The same is true for an Optional. We have to verify that the instance our optional is holding is the same of that we are trying to grab. Since we cannot compare generics directly , the next best thing is to compare the two singleton capabilities itself as they are directly related to the instance they are holding. A lazy just defers initializing or calling a specific object until first access and then stores the result. It provides a way to grab a pointer to an instance of an object before it might be specifically registered. Lazily using objects is quite prevalent in Java itself as can be seen with how Streams work.

Posted
1 hour ago, ChampionAsh5357 said:

No, it has to do with how anything works. Imagine you were trying to cast an instance of Object A to Object B (let's say Object A is LivingEntity and Object B is PlayerEntity). We cannot blindly cast one to the other as not all LivingEntities are PlayerEntities. Therefore, we have to insure that the entity is a player before casting using some sort of check. The same is true for an Optional. We have to verify that the instance our optional is holding is the same of that we are trying to grab. Since we cannot compare generics directly , the next best thing is to compare the two singleton capabilities itself as they are directly related to the instance they are holding. A lazy just defers initializing or calling a specific object until first access and then stores the result. It provides a way to grab a pointer to an instance of an object before it might be specifically registered. Lazily using objects is quite prevalent in Java itself as can be seen with how Streams work.

 

That actually makes it clear. I haven't seen Lazy before until about 3 weeks ago when I stepped back into the Modding world. I also haven't worked with Minecraft modding since 1.12.2 and it was very brief. Prior to that it was only 1.7.10. Also I don't code with Java normally so that works against me, only when working on Minecraft Mods am I utilizing Java so it is somewhat "unfamiliar" to me after not working with it for such a period of time, so when I see something like "Lazy" i get all Huh o_O. But that explanation does make sense so I thank you.

Posted (edited)

LazyOptional is just a lazily-instantiated Optional.

It still holds a value, that value is of type T. T as in LazyOptional<T>

That value gets cast to T when you call someLazy.cast(), so if the value actually stored in the LazyOptional is not actually of type T, the cast will fail.

 

Optionals are just a box wrapped around a concrete object because you don't know if that object actually exists or not (which is why you have to use ifPresent, orElse, or orElseThrow--depending on circumstances).

Edited by Draco18s

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.