Jump to content

[Solved] [1.10.2] Making sword deal extra damage to certain mobs


Recommended Posts

Posted

I'm making a custom sword which is supposed to deal extra damage to Nether mobs (which I've defined as "any mobs immune to fire except shulkers and the Ender Dragon", since that seems to cover all of them exactly, for now). At first I was going to deal with it via event hooks, but then I realized I can just override the ItemSword#hitEntity method and deal the extra damage there.

 

Or so I thought. During testing, if I set the extra damage to something insane like 10000, it works perfectly and one-hit kills Nether mobs. But when I lower the extra damage to be the strength of the full sword damage, the entities aren't taking the proper amount of damage.

 

Here's the code I'm using:

 

package com.IceMetalPunk.amethystic.AmethysticItems;

import com.IceMetalPunk.amethystic.Amethystic;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.monster.EntityShulker;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.util.DamageSource;

public class ItemAmethystSword extends ItemSword {

public final float realAttackDamage;

protected ItemAmethystSword() {
	super(Amethystic.AMETHYST_MATERIAL);
	this.realAttackDamage = 3.0f + Amethystic.AMETHYST_MATERIAL.getDamageVsEntity();
	this.setUnlocalizedName("amethyst_sword").setRegistryName(Amethystic.MODID, "amethyst_sword");
	this.setCreativeTab(Amethystic.AMETHYSTIC_TAB);
}

// Make it deal more damage to Withers and Nether mobs
@Override
public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) {
	super.hitEntity(stack, target, attacker);
	if (target.isImmuneToFire() && !(target instanceof EntityShulker) && !(target instanceof EntityDragon)) {
		System.out.println(this.realAttackDamage);
		if (attacker instanceof EntityPlayer) {
			target.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) attacker), 1.0f + this.realAttackDamage);
		}
		else {
			target.attackEntityFrom(DamageSource.causeMobDamage(attacker), 1.0f + this.realAttackDamage);
		}
	}
	return true;
}

}

 

The numbers I'm using come from the fact that a sword's base attackDamage is 3 plus the material's damage (but since attackDamage is a private member, I'm creating my own here). And then that gets added via attribute modifiers to the player's own 1 damage from punching whenever they equip the sword.

 

The sword does 7 damage (same as diamond), but when I hit a Nether mob, it does less damage somehow. For example, using /entitydata for inspection, one hit dropped an unarmored zombie pigman from 20 health to 13.114-and-change health, less than 7 damage.

 

What am I missing here? This is supposed to be simple xD

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

The code you provided only attacks the enemy with the real attack damage + 1 (for both).

Well, yes. The ItemSword#hitEntity base code doesn't actually deal any damage; in fact, all it does is take item durability in a single line and then return xD I figured since the actual damage is coming from the attribute modifiers of the sword and being applied elsewhere internally, if I just use attackEntityFrom() in the method, it'll stack on top of the usual damage, hence it should be a net total of 2*damage.

 

I tested that by setting the damage amounts to 0 in both calls, and it worked fine, hitting the mobs for normal diamond sword amounts...

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

The sword does 7 damage (same as diamond), but when I hit a Nether mob, it does less damage somehow. For example, using /entitydata for inspection, one hit dropped an unarmored zombie pigman from 20 health to 13.114-and-change health, less than 7 damage.

 

What am I missing here? This is supposed to be simple xD

 

Pigmen have natural armor. Magma cubes, slimes, shulkers, zombies, and The Wither are other mobs that also have natural armor.

 

Item#hitEntity()

is called after the damage from items is done, so your implementation will do more damage than you expect. A better method to override would be

ItemSword#getDamageVsEntity()

.

Posted

The sword does 7 damage (same as diamond), but when I hit a Nether mob, it does less damage somehow. For example, using /entitydata for inspection, one hit dropped an unarmored zombie pigman from 20 health to 13.114-and-change health, less than 7 damage.

 

What am I missing here? This is supposed to be simple xD

 

Pigmen have natural armor. Magma cubes, slimes, shulkers, zombies, and The Wither are other mobs that also have natural armor.

 

Item#hitEntity()

is called after the damage from items is done, so your implementation will do more damage than you expect. A better method to override would be

ItemSword#getDamageVsEntity()

.

 

O_o How did I never know these guys had some natural armor? *Sigh* Okay, then...that makes sense now.

 

The getDamageVsEntity method doesn't have any parameters, so how would I determine which mob is being hit in the override of that?

 

(I'm getting the feeling I'll end up *needing* to handle this in an event handler, though that seems less efficient since it would fire for every attack rather than just attacks with this particular sword...)

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted
A better method to override would be ItemSword#getDamageVsEntity().

I'm unsure about that. getDamageVsEntity() seems to be called only when a mob is deciding whether or not to pick up a fallen item (and wants to compare it to what it already has). Does it also figure into the player's attack calculation? One could try setting a break point to see if it is called during combat.

 

I actually like using the hitEntity method to deal the extra damage. One thing to look out for though: You might then be bypassing the weapon cool-down, re-enabling the hit-spamming that was nerfed by Minecraft's combat upgrade. Decide if you need/want to mimic the partial damage of quick hits.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

A better method to override would be ItemSword#getDamageVsEntity().

I'm unsure about that. getDamageVsEntity() seems to be called only when a mob is deciding whether or not to pick up a fallen item (and wants to compare it to what it already has). Does it also figure into the player's attack calculation? One could try setting a break point to see if it is called during combat.

 

I actually like using the hitEntity method to deal the extra damage. One thing to look out for though: You might then be bypassing the weapon cool-down, re-enabling the hit-spamming that was nerfed by Minecraft's combat upgrade. Decide if you need/want to mimic the partial damage of quick hits.

Yeah, I don't see it being used anywhere else, either.

 

I'm not sure how it would be bypassing the cooldown; you can't trigger the extra damage unless you hit with the sword anyway. As far as I can see, the cooldown is only reset when calling PlayerControllerMP#attackEntity or EntityPlayer#attackTargetEntityWithCurrentItem, but not with attackEntityFrom. Am I missing something?

 

*EDIT* Okay, so some more testing shows that the armor points aren't the problem here, nor am I dealing more damage than expected. In fact, the sword is dealing exactly the same amount of damage as a normal diamond sword. As I said, if I set the extra damage to something crazy like 10000, it works, but with it set to the same strength as normal, it doesn't seem to do any extra damage. I'm confused...

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

I think the point is that

hitEntity

is called even while the cooldown is active.  So you get full bonus damage even if the sword itself is dealing 0.1 damage.

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

I think the point is that

hitEntity

is called even while the cooldown is active.  So you get full bonus damage even if the sword itself is dealing 0.1 damage.

 

Ah, yes, that makes sense. Well, the actual amount of bonus damage still needs calibration, so I may end up recalculating based on the cooldown anyway. But first I need to figure out why it doesn't seem to be doing any bonus damage unless the amount is turned way, way up...

 

*EDIT* Okay, odd...I threw in some debugging console logging, and it seems like target.attackEntityFrom() is returning false. Unfortunately, there are many reasons that would happen, so I guess it's time for me to step through and find out what's going on...

 

*EDIT 2* Well...the importance of breakpoints, everyone. So it turns out the problem here is in hit-based resistance times. After getting hit, there's a small amount of time where an entity will only take damage if the attack is stronger than the previous attack. Since this attack is equivalent, and applied immediately after the first attack, it was being ignored by the resistance time. When I was testing with very high values, those were more than the "previous attack" strength, so it let them through.

 

Okay, then. Now I have a place to start with fixing this. Time to see if I can actually reset the resistance timer in order to apply the second damage...

 

*EDIT 3* If anyone's still reading this... So it turns out the resistance timer is a public member, so that was easy enough. However, in order to take cooldown into consideration, it introduces another problem: the bonus damage is triggering when the cooldown has just been reset from the normal attack, meaning it actually does no damage if cooldown is considered, and this code will only see a value of 0 for the cooldown no matter what.

 

So is there a way to get the "previous cooldown", as it were? Or should I just be ignoring cooldown and having full bonus damage? (I thought about just dealing the equivalent of target.lastDamage, but that's also protected...I hope I won't have to hack my way through this via reflection...)

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

I think the point is that

hitEntity

is called even while the cooldown is active.  So you get full bonus damage even if the sword itself is dealing 0.1 damage.

 

Ah, yes, that makes sense. Well, the actual amount of bonus damage still needs calibration, so I may end up recalculating based on the cooldown anyway. But first I need to figure out why it doesn't seem to be doing any bonus damage unless the amount is turned way, way up...

 

*EDIT* Okay, odd...I threw in some debugging console logging, and it seems like target.attackEntityFrom() is returning false. Unfortunately, there are many reasons that would happen, so I guess it's time for me to step through and find out what's going on...

 

*EDIT 2* Well...the importance of breakpoints, everyone. So it turns out the problem here is in hit-based resistance times. After getting hit, there's a small amount of time where an entity will only take damage if the attack is stronger than the previous attack. Since this attack is equivalent, and applied immediately after the first attack, it was being ignored by the resistance time. When I was testing with very high values, those were more than the "previous attack" strength, so it let them through.

 

Okay, then. Now I have a place to start with fixing this. Time to see if I can actually reset the resistance timer in order to apply the second damage...

 

*EDIT 3* If anyone's still reading this... So it turns out the resistance timer is a public member, so that was easy enough. However, in order to take cooldown into consideration, it introduces another problem: the bonus damage is triggering when the cooldown has just been reset from the normal attack, meaning it actually does no damage if cooldown is considered, and this code will only see a value of 0 for the cooldown no matter what.

 

So is there a way to get the "previous cooldown", as it were? Or should I just be ignoring cooldown and having full bonus damage? (I thought about just dealing the equivalent of target.lastDamage, but that's also protected...I hope I won't have to hack my way through this via reflection...)

I am currently wondering where entities are actually damage by the player now... the best way to figure this out would probably be to see where getDamageVsEntity() is called.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

It's got nothing to do with ItemSword#getDamageVsEntity(). Entities are damaged by the player via a call to PlayerControllerMP#attackEntity, which is called in Minecraft#clickMouse. It just uses the player's strength modifier, which is updated whenever you change your equipped item. (In other words, the sword doesn't deal any damage, it just "makes you hit stronger" by an amount equal to the sword's attack strength when it's equipped; that strength is calculated in the item's constructor based on its material's attack damage.)

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

It's got nothing to do with ItemSword#getDamageVsEntity().

If this isnt called when an entity is attacked by an item from the player there would be no point in the methods existence. PlayerControllerMp#attackEntity calls other methods figure out which one happens before resistance times are sent that are in the items class that give you the target then deal the damage there (hopefully without recursion).

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

As previously mentioned, ItemSword#getDamageVsEntity is only called in one place: when a mob that can pick up loot decides whether to pick up the item or not. It's how the mobs decide which swords are better and which should be dropped, since the ItemSword#attackDamage member is private and so couldn't be accessed from inside the mob class.

 

As for cooldown times... there are literally only two lines of code between when the game gets the normal attack strength based on the current cooldown and when it resets that cooldown. And those two lines are just straight arithmetic. There's nowhere to hook into between them...which is extremely unfortunate...

 

However, just before that calculation is made, Forge does fire an onPlayerAttackTarget event...so even though I was trying to avoid doing this with events due to its niche situations, I might have to. And the player class does have a special CooldownTracker that's public, so if I hook into it there, I should have access to the full cooldown information. Maybe; it seems quite decoupled from the ticksSinceLastSwing that all the damage calculations use, so I'll have to see what I can finagle out of it.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

You've reached the conclusion that I saw yesterday. Since you seem to want to preserve the weapon recharge rule, but still use hitEntity, I suggest this:

 

Write a simple event handler that detects your sword, peeks at the cooldown percentage, and then stores it somewhere to use a moment later in your implementation of hitEntity. Because the code-path between storage and use is so short (within one method), you might even be safe using a public field inside class ItemAmethystSword. If you nest your event handler class inside your sword class, then the field might not even need to be public.

 

Then rewrite hitEntity to implement the partial damage and also compensate for or bypass the mob's temporary immunity.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

If I'm going to end up using event handlers anyway (which I think I'm just going to have to live with), then there's a more elegant solution: there's the PlayerEvent.AttackEntityEvent, which fires in the same method as damage calculations, but shortly before the damage calculations, i.e. when the cooldown is exactly the value needed to calculate cooldown-adjusted damage. So I can hook into that, check if the item in the player's main hand is the custom sword, and if so, cancel the default event and recalculate the damage and deal it myself (essentially copy-pasting the default code as much as possible, but with a different damage value).

 

I was hoping to avoid event handlers since they fire more generically than I'm going to need, but I guess a little inefficiency will just have to exist in this.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

An "is this my sword?" check is super cheap.  Don't even worry about it.

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

An "is this my sword?" check is super cheap.  Don't even worry about it.

Fair enough. I have a habit of trying to over-optimize to the point of impracticality xD

 

But yeah, my idea with the AttackEntityEvent hook--and a big, copypasta method for recreating the attack plus a multiplier--worked perfectly! So I guess this thread can be considered solved now.

 

Thanks for everyone's help!

Whatever Minecraft needs, it is most likely not yet another tool tier.

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

×
×
  • Create New...

Important Information

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