Jump to content

Recommended Posts

Posted
public class CustomEntity extends FlyingEntity {

	public CustomEntity(EntityType<? extends FlyingEntity> type, World worldIn) {
		super(type, worldIn);
		moveController = new FlyingMovementController(this, 60, true);
	}

	public static AttributeModifierMap.MutableAttribute setAttributes(){
		return MobEntity.func_233666_p_()
				.func_233815_a_(Attributes.field_233822_e_, (double) 5.0f)
				.func_233815_a_(Attributes.field_233821_d_, (double) 5.0f)
				.func_233815_a_(Attributes.field_233818_a_, 10);
	}

	@Override
	public void registerGoals() {
		super.registerGoals();
		goalSelector.addGoal(0, new FollowOwnerGoal());
		goalSelector.addGoal(1, new LookAtGoal(this, PlayerEntity.class, 5));
	}

	@Override
	protected PathNavigator createNavigator(World worldIn) {
		return new FlyingPathNavigator(this, worldIn);
	}

	private class FollowOwnerGoal extends Goal {

		private static final int DISTANCE = 5;

		private FollowOwnerGoal() {
			setMutexFlags(EnumSet.of(Goal.Flag.MOVE));
		}

		@Override
		public boolean shouldExecute() {
			return getOwner() != null && getDistanceSq(getOwner()) > DISTANCE * DISTANCE;
		}

		@Override
		public boolean shouldContinueExecuting() {
			return shouldExecute() && !getNavigator().noPath();
		}

		@Override
		public void tick() {
			getNavigator().tryMoveToXYZ(getOwner().getPosX(), getOwner().getPosYEye(), getOwner().getPosZ(), 1);
		}
	}
}
private void setup(final FMLCommonSetupEvent event) {
		DeferredWorkQueue.runLater(() -> {
			GlobalEntityTypeAttributes.put(RegistryHandler.CUSTOM_ENTITY.get(), CustomEntity.setAttributes().func_233813_a_());
		});
	}

This should be all the relevant code. Basically, no matter what the speed attribute of my entity is, it is always insanely slow. I thought it might have to do with the FlyingPathNavigator and MovementController's just not using the right speed, but I also changed the generic movement speed attribute and nothing changed. I feel like I probably needed to override another method or something. What have I done wrong?

Posted (edited)
6 hours ago, DavidQF555 said:

getNavigator().tryMoveToXYZ(getOwner().getPosX(), getOwner().getPosYEye(), getOwner().getPosZ(), 1);

A number 1 you pass here is actually double and defines movement speed multiplier.

Resulting movement speed will equal to speed attribute * this parameter, as shown at MovementController::tick.

So, you may try change 1 to 1.0d, and then set there, for example, 2.0d.

Edited by Dzuchun

Everything said above may be absolutely wrong. No rights reserved.

Posted
5 hours ago, Dzuchun said:

A number 1 you pass here is actually double and defines movement speed multiplier.

Resulting movement speed will equal to speed attribute * this parameter, as shown at MovementController::tick.

So, you may try change 1 to 1.0d, and then set there, for example, 2.0d.

I changed it to 2.0D and nothing has really changed. Using livingTick() to print out speed, it constantly switches between the number I set in the tryMoveToXYZ() and 0. It just ignores my attribute, and the speed printed is also not really applied to how fast the actual entity is. I put in 100.0D and nothing changed. 

Posted

Where from do you execute setAttributes method?

It's static, so it does not override something.

Also, you'd better provide full source code(using github, for example), because usually errors are in the places you do not expect them :)

Everything said above may be absolutely wrong. No rights reserved.

Posted
19 minutes ago, Dzuchun said:

Where from do you execute setAttributes method?

It's static, so it does not override something.

Also, you'd better provide full source code(using github, for example), because usually errors are in the places you do not expect them :)

The setAttributes method is in the code I sent, in the Main class. I know it works because FlyingPathNavigator does not even work without a flying speed. Also, its health is actually 10. 

Posted

Let me just post the code of all the classes that have some relevance: 

ublic class CustomEntity extends FlyingEntity {

  private LivingEntity owner;
  
	public CustomEntity(EntityType<? extends FlyingEntity> type, World worldIn, LivingEntity owner) {
		super(type, worldIn);
		moveController = new FlyingMovementController(this, 60, true);
      this.owner = owner;
	}
  
  public LivingEntity getOwner(){
   return owner; 
  }

	public static AttributeModifierMap.MutableAttribute setAttributes(){
		return MobEntity.func_233666_p_()
				.func_233815_a_(Attributes.field_233822_e_, (double) 5.0f)
				.func_233815_a_(Attributes.field_233821_d_, (double) 5.0f)
				.func_233815_a_(Attributes.field_233818_a_, 10);
	}

	@Override
	public void registerGoals() {
		super.registerGoals();
		goalSelector.addGoal(0, new FollowOwnerGoal());
		goalSelector.addGoal(1, new LookAtGoal(this, PlayerEntity.class, 5));
	}

	@Override
	protected PathNavigator createNavigator(World worldIn) {
		return new FlyingPathNavigator(this, worldIn);
	}

	private class FollowOwnerGoal extends Goal {

		private static final int DISTANCE = 5;

		private FollowOwnerGoal() {
			setMutexFlags(EnumSet.of(Goal.Flag.MOVE));
		}

		@Override
		public boolean shouldExecute() {
			return getOwner() != null && getDistanceSq(getOwner()) > DISTANCE * DISTANCE;
		}

		@Override
		public boolean shouldContinueExecuting() {
			return shouldExecute() && !getNavigator().noPath();
		}

		@Override
		public void tick() {
			getNavigator().tryMoveToXYZ(getOwner().getPosX(), getOwner().getPosYEye(), getOwner().getPosZ(), 1);
		}
	}
}
@SuppressWarnings("deprecation")
@Mod("testmod")
public class TestMod {

	public static final String MOD_ID = "testmod";
	public static final ItemGroup TAB = new ItemGroup("testmod") {
		@Override
		public ItemStack createIcon() {
			return new ItemStack(RegistryHandler.RUBY.get());
		}
	};

	public TestMod() {
		FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
		FMLJavaModLoadingContext.get().getModEventBus().addListener(this::doClientStuff);

		RegistryHandler.init();

		MinecraftForge.EVENT_BUS.register(this);
	}

	private void setup(final FMLCommonSetupEvent event) {
		DeferredWorkQueue.runLater(() -> {
			GlobalEntityTypeAttributes.put(RegistryHandler.CUSTOM_ENTITY.get(), CustomEntity.setAttributes().func_233813_a_());
		});
	}

	private void doClientStuff(final FMLClientSetupEvent event) {}

}
public class RegistryHandler {

	public static final DeferredRegister<EntityType<?>> ENTITY_TYPES = DeferredRegister.create(ForgeRegistries.ENTITIES, TestMod.MOD_ID);

	public static final RegistryObject<EntityType<CustomEntity>> CUSTOM_ENTITY = ENTITY_TYPES.register("custom_entity", () -> EntityType.Builder.create(new CustomFactory(), EntityClassification.AMBIENT).size(0.9f, 0.9f).build(new ResourceLocation(TestMod.MOD_ID, "custom_entity").toString()));

	public static void init() {
		IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
		ENTITY_TYPES.register(bus);
	}
public class CustomFactory implements EntityType.IFactory<CustomEntity> {
		@Override
		public CustomEntity create(EntityType<CustomEntity> type, World world) {
			return new CustomEntity(type, world, null);
		}
	}
public class CustomItem extends BasicItem {

	@Override
	public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
		Vector3d spawn = playerIn.getEyePosition(1).add(playerIn.getLookVec().mul(2, 2, 2));
		CustomEntity light = new CustomEntity(RegistryHandler.CUSTOM_ENTITY.get(), worldIn, playerIn);
		if(light.canSpawn(worldIn, SpawnReason.MOB_SUMMONED)) {
			light.setPosition(spawn.x, spawn.y, spawn.z);
			worldIn.addEntity(light);
			ItemStack item = playerIn.getHeldItem(handIn);
			item.setCount(item.getCount() - 1);
			playerIn.setHeldItem(handIn, item);
		}
		return ActionResult.resultPass(playerIn.getHeldItem(handIn));
	}
}

 

Posted
1 hour ago, DavidQF555 said:

public class CustomFactory implements EntityType.IFactory<CustomEntity> 
{ 
  @Override
  public CustomEntity create(EntityType<CustomEntity> type, World world)
  { 
    return new CustomEntity(type, world, null); 
  } 
}

 

You may use lambda-expression for that.

It won't help you at all, but you'll get rid of some excess code.

1 hour ago, DavidQF555 said:

private class FollowOwnerGoal extends Goal

Minecraft has FollowOwnerGoal for you to have a template (it requires TameableEntity).

The problem may be that you set a new path every tick. Stock FollowOwnerGoal does it every 10 ticks. (not sure)

Everything said above may be absolutely wrong. No rights reserved.

Posted
1 hour ago, Dzuchun said:

You may use lambda-expression for that.

It won't help you at all, but you'll get rid of some excess code.

Minecraft has FollowOwnerGoal for you to have a template (it requires TameableEntity).

The problem may be that you set a new path every tick. Stock FollowOwnerGoal does it every 10 ticks. (not sure)

I checked it, it basically does the same thing except check more conditions like whether sitting or not. I updated my code to: 

private class FollowOwnerGoal extends Goal {

		private static final int DISTANCE = 5;
		private static final int COOLDOWN = 200;
		private int cooldown;

		private FollowOwnerGoal() {
			setMutexFlags(EnumSet.of(Goal.Flag.MOVE));
			cooldown = 0;
		}

		@Override
		public boolean shouldExecute() {
			return getOwner() != null && getDistanceSq(getOwner()) > DISTANCE * DISTANCE;
		}

		@Override
		public boolean shouldContinueExecuting() {
			return shouldExecute() && !getNavigator().noPath();
		}
		
		@Override
		public void resetTask() {
			cooldown = 0;
			getNavigator().clearPath();
		}

		@Override
		public void tick() {
			cooldown = Math.max(0, cooldown - 1);
			if(cooldown == 0) {
				getNavigator().tryMoveToXYZ(getOwner().getPosX(), getOwner().getPosYEye(), getOwner().getPosZ(), 100.0D);
				cooldown = COOLDOWN;
			}
		}
	}

To attempt to replicate the Tameable one, but it still has the same effect. I think it has something to do with either switching to FlyingMovementController or FlyingPathNavigator, but I cannot figure out what the problem is. 

Posted (edited)

I used to experiment with creating custom entities at 1.15.2, but seems like not much changed since then*nevermind*. Here is my repository.

Please, do not use it as manual, it's terrible in fact. All you need about AI is at HappyDolphinEntity class, which defines a pink horned flying dolphin that eats flowers accidentally (don't ask me why).

In that class you may see my own WanderingGoal, (because I was to stupid to use existing one, yea) and all sort of things I made to get it working.

I'm really sorry for posting this code here, and once again, THIS IS NOT A MANUAL.

Read sign.

Edited by Dzuchun

Everything said above may be absolutely wrong. No rights reserved.

Posted
33 minutes ago, Dzuchun said:

I used to experiment with creating custom entities at 1.15.2, but seems like not much changed since then. Here is my repository.

Please, do not use it as manual, it's terrible in fact. All you need about AI is at HappyDolphinEntity class, which defines a pink horned flying dolphin that eats flowers accidentally (don't ask me why).

In that class you may see my own WanderingGoal, (because I was to stupid to use existing one, yea) and all sort of things I made to get it working.

I'm really sorry for posting this code here, and once again, THIS IS NOT A MANUAL.

Read sign.

private class FollowOwnerGoal extends Goal {

		private static final int DISTANCE = 5;

		private FollowOwnerGoal() {
			setMutexFlags(EnumSet.of(Goal.Flag.MOVE));
		}

		@Override
		public boolean shouldExecute() {
			return getNavigator().noPath() && getOwner() != null && getDistanceSq(getOwner()) > DISTANCE * DISTANCE;
		}

		@Override
		public boolean shouldContinueExecuting() {
			return false;
		}
		
		@Override
		public void startExecuting() {
			super.startExecuting();
			getNavigator().tryMoveToXYZ(getOwner().getPosX(), getOwner().getPosYEye(), getOwner().getPosZ(), 100);
		}
	}

I really simplified mine. Your code has a lot more factors, but I just need it to move, so this should work, but it doesn't consider the speed at all

Posted
1 minute ago, DavidQF555 said:

@Override
public boolean shouldContinueExecuting() 
{ 
 return false;
}

 

This means that after 1 tick your task gets interrupted and another one selected.

Everything said above may be absolutely wrong. No rights reserved.

Posted
Just now, Dzuchun said:

This means that after 1 tick your task gets interrupted and another one selected.

It doesn't really matter though. It currently only has 1 goal and that goal really only needs to run the starting code

Posted
private class FollowOwnerGoal extends Goal {

		private static final double DISTANCE = 5;

		private FollowOwnerGoal() {
			setMutexFlags(EnumSet.of(Goal.Flag.MOVE));
		}

		@Override
		public boolean shouldExecute() {
			Entity owner = getOwner();
			if (owner == null) {
				return false;
			} else if (owner.isSpectator()) {
				return false;
			} else return !(getDistanceSq(owner) < DISTANCE * DISTANCE);
		}

		/**
		 * Returns whether an in-progress EntityAIBase should continue executing
		 */
		public boolean shouldContinueExecuting() {
			if (getNavigator().noPath() || getOwner() == null) {
				return false;
			} else {
				return !(getDistanceSq(getOwner()) <= DISTANCE * DISTANCE);
			}
		}

		/**
		 * Reset the task's internal state. Called when this task is interrupted by another one
		 */
		public void resetTask() {
		getNavigator().clearPath();
			LOGGER.info("Reset");
		}

		/**
		 * Keep ticking a continuous task that has already been started
		 */
		public void tick() {
			if(getOwner() != null) {
				getLookController().setLookPositionWithEntity(getOwner(), 10.0F, getVerticalFaceSpeed());
				if (!getLeashed() && !isPassenger()) {
					LOGGER.info("controller: " + moveController.getSpeed() + " AI: " + getAIMoveSpeed());
					getNavigator().tryMoveToEntityLiving(getOwner(), 100);

				}
			}
		}
	}

I've basically copied the Tameable version now. Is it normal for the "reset" to be called every 5 ticks? The other logger message is completely normal

Posted

I figured out that the AI Speed in CustomEntity is changing to speed multiplier * attribute, but the speed in moveController was staying to exactly the speed multiplier, but the actual speed moving doesn't change

  • 3 weeks later...

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

    • So me and a couple of friends are playing with a shitpost mod pack and one of the mods in the pack is corail tombstone and for some reason there is a problem with it, where on death to fire the player will get kicked out of the server and the tombstone will not spawn basically deleting an entire inventory, it doesn't matter what type of fire it is, whether it's from vanilla fire/lava, or from modded fire like ice&fire/lycanites and it's common enough to where everyone on the server has experienced at least once or twice and it doesn't give any crash log. a solution to this would be much appreciated thank you!
    • It is 1.12.2 - I have no idea if there is a 1.12 pack
    • Okay, but does the modpack works with 1.12 or just with 1.12.2, because I need the Forge client specifically for Minecraft 1.12, not 1.12.2
    • 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() ); } }  
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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