Posted April 9, 20223 yr I want to make a custom attack reach attribute, however it doesn't register when I launch my game. Yes, any events using it were register to the mod event bus. I'm using DeferredRegister. Do I need to work with capabilities or something?
April 9, 20223 yr Author Registry Class: public static final DeferredRegister<Attribute> ATTRIBUTES = DeferredRegister.create(ForgeRegistries.ATTRIBUTES, ReachMod.MODID); //ATTRIBUTES public static final RegistryObject<Attribute> ATTACK_REACH = ATTRIBUTES.register("attack_reach", () -> (Attribute) new RangedAttribute("attribute.mod.attack_reach", 5.0D, 0.0D, 1024.0D).setSyncable(true)); //MODIFIERS public static final UUID ATTACH_REACH_MODIFIER = UUID.fromString("7cc9a781-fdde-4e1b-85fe-acb912fc0430"); Main Class: //Register stuff IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); ModAttributes.ATTRIBUTES.register(bus); Extra stuff (events): @EventBusSubscriber(bus = Bus.MOD) public static class ClientHelper{ @SuppressWarnings("unused") private static RayTraceResult getEntityMouseOverExtended(float reach) { BlockRayTraceResult blockRayTraceResult = null; RayTraceResult result = null; Minecraft mc = Minecraft.getInstance(); Entity viewEntity = mc.crosshairPickEntity; PlayerController p = mc.gameMode; if (viewEntity != null) { double d0 = reach; RayTraceResult rayTrace = viewEntity.pick(d0, 0.0F, false); Vector3d eyePos = viewEntity.getEyePosition(0.0F); boolean flag = false; double d1 = d0; if (p.hasFarPickRange() && d1 < 6.0D) { d1 = 6.0D; d0 = d1; } else if (d0 > reach) { flag = true; } d1 *= d1; if (rayTrace != null) d1 = rayTrace.getLocation().distanceToSqr(eyePos); Vector3d lookVec = viewEntity.getEyePosition(1.0F); Vector3d attackVec = eyePos.add(lookVec.x * d0, lookVec.y * d0, lookVec.z * d0); AxisAlignedBB expBounds = viewEntity.getBoundingBox().expandTowards(lookVec.scale(d0)).inflate(1.0D, 1.0D, 1.0D); EntityRayTraceResult entityRayTrace = ProjectileHelper.getEntityHitResult(viewEntity, eyePos, attackVec, expBounds, entity -> (!entity.isSpectator() && entity.canBeCollidedWith()), d1); if (entityRayTrace != null) { Vector3d hitVec = entityRayTrace.getLocation(); double d2 = eyePos.distanceToSqr(hitVec); if (flag && d2 > (reach * reach)) { blockRayTraceResult = BlockRayTraceResult.miss(hitVec, Direction.getNearest(lookVec.x, lookVec.y, lookVec.z), new BlockPos(hitVec)); } else if (d2 < d1 || blockRayTraceResult == null) { EntityRayTraceResult entityRayTraceResult = entityRayTrace; } } else { blockRayTraceResult = BlockRayTraceResult.miss(attackVec, Direction.getNearest(lookVec.x, lookVec.y, lookVec.z), new BlockPos(attackVec)); } } return (RayTraceResult)blockRayTraceResult; } private static void checkForReachAttack() { Minecraft mc = Minecraft.getInstance(); ClientPlayerEntity clientPlayerEntity = mc.player; if (clientPlayerEntity == null || clientPlayerEntity.isSpectator()) return; double reach = (float)clientPlayerEntity.getAttributeValue(ModAttributes.ATTACK_REACH.get()); if (reach == ModAttributes.ATTACK_REACH.get().getDefaultValue()) return; RayTraceResult rayTrace = getEntityMouseOverExtended((float)reach); if (!(rayTrace instanceof EntityRayTraceResult)) return; EntityRayTraceResult entityRayTrace = (EntityRayTraceResult)rayTrace; Entity entityHit = entityRayTrace.getEntity(); if (entityHit != null && entityHit.invulnerableTime == 0 && entityHit != clientPlayerEntity && entityHit != clientPlayerEntity.getControllingPassenger()) { float velocity = 0.0F; if (clientPlayerEntity.getControllingPassenger() != null) { Entity riding = clientPlayerEntity.getControllingPassenger(); Vector3d vec = riding.getDeltaMovement(); velocity = (float)vec.length(); } PacketHandler.sendPacketToServer(new PacketReach(velocity, entityHit.getId())); } } @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) @SuppressWarnings("resource") public static void mouseEvent(InputEvent.MouseInputEvent event) { if (Minecraft.getInstance().level == null || Minecraft.getInstance().screen == null || Minecraft.getInstance().isPaused()) return; KeyBinding keyAttack = Minecraft.getInstance().options.keyAttack; if (event.getButton() == keyAttack.getKey().getValue() && event.getAction() == 1 && ModAttributes.ATTACK_REACH.isPresent()) checkForReachAttack(); } } All I need is to register the events and my registries to the mod event bus, right? Edited April 10, 20223 yr by Ninjaguy169
April 9, 20223 yr 7 minutes ago, Ninjaguy169 said: All I need is to register the events and my registries to the mod event bus, right? InputEvent.MouseInputEvent is a Forge Bus Event, only the registry Events are Mod Bus Events (all Events which implements IModBusEvent)
April 9, 20223 yr Author Whenever I subscribe to the forge event bus, the game crashes indicating that the attribute is null
April 9, 20223 yr Author Description: Unexpected error java.lang.IllegalArgumentException: Can't find attribute reachmod:attack_reach at net.minecraft.entity.ai.attributes.AttributeModifierMap.getAttributeInstance(AttributeModifierMap.java:21) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.entity.ai.attributes.AttributeModifierMap.getValue(AttributeModifierMap.java:28) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.entity.ai.attributes.AttributeModifierManager.getValue(AttributeModifierManager.java:62) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.entity.LivingEntity.getAttributeValue(LivingEntity.java:1731) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,re:mixin,pl:accesstransformer:B} at com.creator.reachmod.client.ClientEvent$ReachClientHelper.checkForReachAttack(ClientEvent.java:105) ~[main/:?] {re:classloading} at com.creator.reachmod.client.ClientEventEvent$ReachClientHelper.mouseEvent(ClientEvent.java:131) ~[main/:?] {re:classloading} at net.minecraftforge.eventbus.ASMEventHandler_60_ReachClientHelper_mouseEvent_MouseInputEvent.invoke(.dynamic) ~[?:?] {} at net.minecraftforge.eventbus.ASMEventHandler.invoke(ASMEventHandler.java:85) ~[eventbus-4.0.0.jar:?] {} at net.minecraftforge.eventbus.EventBus.post(EventBus.java:302) ~[eventbus-4.0.0.jar:?] {} at net.minecraftforge.eventbus.EventBus.post(EventBus.java:283) ~[eventbus-4.0.0.jar:?] {} at net.minecraftforge.client.ForgeHooksClient.fireMouseInput(ForgeHooksClient.java:811) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.client.MouseHelper.onPress(MouseHelper.java:118) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.MouseHelper.lambda$null$4(MouseHelper.java:181) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.util.concurrent.ThreadTaskExecutor.execute(ThreadTaskExecutor.java:94) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,re:mixin,pl:accesstransformer:B} at net.minecraft.client.MouseHelper.lambda$setup$5(MouseHelper.java:180) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at org.lwjgl.glfw.GLFWMouseButtonCallbackI.callback(GLFWMouseButtonCallbackI.java:36) ~[lwjgl-glfw-3.2.2.jar:build 10] {} at org.lwjgl.system.JNI.invokeV(Native Method) ~[lwjgl-3.2.2.jar:build 10] {} at org.lwjgl.glfw.GLFW.glfwPollEvents(GLFW.java:3101) ~[lwjgl-glfw-3.2.2.jar:build 10] {} at com.mojang.blaze3d.systems.RenderSystem.flipFrame(RenderSystem.java:102) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.MainWindow.updateDisplay(MainWindow.java:306) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.runTick(Minecraft.java:997) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.run(Minecraft.java:607) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.main.Main.main(Main.java:184) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] {} at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?] {} at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] {} at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?] {} at net.minecraftforge.userdev.FMLUserdevClientLaunchProvider.lambda$launchService$0(FMLUserdevClientLaunchProvider.java:52) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [modlauncher-8.1.3.jar:?] {} at net.minecraftforge.userdev.LaunchTesting.main(LaunchTesting.java:108) [forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {} A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- Head -- Thread: Render thread Stacktrace: at net.minecraft.entity.ai.attributes.AttributeModifierMap.getAttributeInstance(AttributeModifierMap.java:21) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.entity.ai.attributes.AttributeModifierMap.getValue(AttributeModifierMap.java:28) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.entity.ai.attributes.AttributeModifierManager.getValue(AttributeModifierManager.java:62) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.entity.LivingEntity.getAttributeValue(LivingEntity.java:1731) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,re:mixin,pl:accesstransformer:B} at com.creator.reachmod.client.ClientEvent$ReachClientHelper.checkForReachAttack(ClientEvent.java:105) ~[main/:?] {re:classloading} at com.creator.reachmod.client.ClientEvent$ReachClientHelper.mouseEvent(ClientEvent.java:131) ~[main/:?] {re:classloading} at net.minecraftforge.eventbus.ASMEventHandler_60_ReachClientHelper_mouseEvent_MouseInputEvent.invoke(.dynamic) ~[?:?] {} at net.minecraftforge.eventbus.ASMEventHandler.invoke(ASMEventHandler.java:85) ~[eventbus-4.0.0.jar:?] {} at net.minecraftforge.eventbus.EventBus.post(EventBus.java:302) ~[eventbus-4.0.0.jar:?] {} at net.minecraftforge.eventbus.EventBus.post(EventBus.java:283) ~[eventbus-4.0.0.jar:?] {} at net.minecraftforge.client.ForgeHooksClient.fireMouseInput(ForgeHooksClient.java:811) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading} at net.minecraft.client.MouseHelper.onPress(MouseHelper.java:118) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.MouseHelper.lambda$null$4(MouseHelper.java:181) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.util.concurrent.ThreadTaskExecutor.execute(ThreadTaskExecutor.java:94) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,re:mixin,pl:accesstransformer:B} at net.minecraft.client.MouseHelper.lambda$setup$5(MouseHelper.java:180) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at org.lwjgl.glfw.GLFWMouseButtonCallbackI.callback(GLFWMouseButtonCallbackI.java:36) ~[lwjgl-glfw-3.2.2.jar:build 10] {} at org.lwjgl.system.JNI.invokeV(Native Method) ~[lwjgl-3.2.2.jar:build 10] {} at org.lwjgl.glfw.GLFW.glfwPollEvents(GLFW.java:3101) ~[lwjgl-glfw-3.2.2.jar:build 10] {} at com.mojang.blaze3d.systems.RenderSystem.flipFrame(RenderSystem.java:102) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A} -- Affected level -- Details: All players: 1 total; [ClientPlayerEntity['Dev'/407, l='ClientLevel', x=107.50, y=84.00, z=-191.50]] Chunk stats: Client Chunk Cache: 841, 529 Level dimension: minecraft:overworld Level spawn location: World: (112,78,-192), Chunk: (at 0,4,0 in 7,-12; contains blocks 112,0,-192 to 127,255,-177), Region: (0,-1; contains chunks 0,-32 to 31,-1, blocks 0,0,-512 to 511,255,-1) Level time: 179 game time, 179 day time Server brand: forge Server type: Integrated singleplayer server Stacktrace: at net.minecraft.client.world.ClientWorld.fillReportDetails(ClientWorld.java:447) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A,re:mixin,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.fillReport(Minecraft.java:2031) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.run(Minecraft.java:628) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.main.Main.main(Main.java:184) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {re:classloading,pl:runtimedistcleaner:A} at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] {} at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?] {} at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] {} at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?] {} at net.minecraftforge.userdev.FMLUserdevClientLaunchProvider.lambda$launchService$0(FMLUserdevClientLaunchProvider.java:52) ~[forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [modlauncher-8.1.3.jar:?] {} at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [modlauncher-8.1.3.jar:?] {} at net.minecraftforge.userdev.LaunchTesting.main(LaunchTesting.java:108) [forge-1.16.5-36.2.33_mapped_official_1.16.5.jar:?] {} Edited April 9, 20223 yr by Ninjaguy169
April 10, 20223 yr Author So the attribute should work. I have it registered in the EntityAttributeModificationEvent, but when I try to modify it for an item, it doesn't work. Do I need to use events?
April 10, 20223 yr Author EntityAttributeModificationEvent: @SubscribeEvent public static void onEntityAttributeModificationEvent(final EntityAttributeModificationEvent event) { event.add(EntityType.PLAYER, ForgeMod.REACH_DISTANCE.get()); } Test Weapon Item: protected static final UUID ATTACK_KNOCKBACK_MODIFIER = UUID.fromString("C59EC38E-DC43-11EB-BA80-0242AC130004"); public static final UUID REACH_MODIFIER = UUID.fromString("5C05J864-4748-24CE-90D6-0242AC170006"); private final Multimap<Attribute, AttributeModifier> attributeModifiers; public AnimationFactory factory = new AnimationFactory(this); public TestItem(IItemTier t, int dmg, float speed, double reachDistance, double knockBack, Properties prop) { super(t, dmg, speed, prop); float attackDamage = (float) dmg + t.getAttackDamageBonus(); ImmutableMultimap.Builder<Attribute, AttributeModifier> builder = ImmutableMultimap.builder(); builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Weapon modifier", dmg, AttributeModifier.Operation.ADDITION)); builder.put(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_UUID, "Weapon modifier", speed, AttributeModifier.Operation.ADDITION)); ForgeMod.getInstance(); if (ForgeMod.REACH_DISTANCE.isPresent()) { builder.put(ForgeMod.REACH_DISTANCE.get(), new AttributeModifier(REACH_MODIFIER, "Weapon modifier", reachDistance, AttributeModifier.Operation.ADDITION)); } builder.put(Attributes.ATTACK_KNOCKBACK, new AttributeModifier(ATTACK_KNOCKBACK_MODIFIER, "Weapon modifier", knockBack, AttributeModifier.Operation.ADDITION)); this.attributeModifiers = builder.build(); } @Override public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(EquipmentSlotType equipmentSlot) { return equipmentSlot == EquipmentSlotType.MAINHAND ? this.attributeModifiers : super.getDefaultAttributeModifiers(equipmentSlot); } Registry Item: public static final RegistryObject<TestItem> TEST_ITEM = ITEMS.register("test_item", () -> new TestItem(ModItemTiers.TEST, 100, -3.2F, 15F, 0, new Item.Properties().rarity(Rarity.EPIC).tab(ModItemGroups.EQUIPMENT))); Pretty sure I need to do something else, although I just can't seem to lay my finger on it. Edited April 10, 20223 yr by Ninjaguy169
April 10, 20223 yr Author Yeah, I figured. So I got it to work (finally), but is there a specific event I can use to see if the player is holding a certain item and change the attribute's value based on that?
April 10, 20223 yr Author I haven't really worked with lazily initialized stuff before, but so far I've created: public static final Lazy<Multimap<Attribute, AttributeModifier>> LAZY = Lazy.of(() -> modifierMap); Forgive me for acting dumb, but may I get a bit more clarity on what to do? Edit: So for the method "getAttributeModifiers(EquipmentSlotType slot, ItemStack stack)", I'd just return return slot == EquipmentSlotType.MAINHAND ? LAZY.get() : super.getAttributeModifiers(slot, stack); is that right? Edited April 10, 20223 yr by Ninjaguy169
April 15, 20223 yr Author Ah alr, so a lambda? public final Lazy<Multimap<Attribute, AttributeModifier>> LAZY = Lazy.of(() -> { //Create a new MultiMap using ArrayListMultiMap.create(), probably not make it null Multimap<Attribute, AttributeModifier> attributeModifiers = null; return attributeModifiers; }); Then I would go about, modifying it inside the "getAttributeValue" method, or is there something else I need to do? Edited April 15, 20223 yr by Ninjaguy169
April 16, 20223 yr 20 hours ago, diesieben07 said: create your map inside the supplier you need to add all values to the Multimap inside the supplier Edited April 16, 20223 yr by Luis_ST
April 18, 20223 yr Author So, public final Lazy<Multimap<Attribute, AttributeModifier>> LAZY = Lazy.of(() -> { ImmutableMultimap.Builder<Attribute, AttributeModifier> builder = ImmutableMultimap.builder(); builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Weapon modifier", damage, AttributeModifier.Operation.ADDITION)); builder.put(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_UUID, "Weapon modifier", speed, AttributeModifier.Operation.ADDITION)); if (ForgeMod.REACH_DISTANCE.isPresent()) { builder.put(ForgeMod.REACH_DISTANCE.get(), new AttributeModifier(ATTACK_REACH_MODIFIER, "Weapon modifier", reach, AttributeModifier.Operation.ADDITION)); } builder.put(Attributes.ATTACK_KNOCKBACK, new AttributeModifier(ATTACK_KNOCKBACK_MODIFIER, "Weapon modifier", kb, AttributeModifier.Operation.ADDITION)); Multimap<Attribute, AttributeModifier> attributeModifiers = ArrayListMultimap.create(); attributeModifiers = builder.build(); return attributeModifiers; }); Then I set the new value in the EntityAttributeModificationEvent to whatever static int I have in the item's class? EDIT: I finally got it to work after adding all the values inside the map as you told me to. Thanks a bunch. Edited April 18, 20223 yr by Ninjaguy169
April 18, 20223 yr 50 minutes ago, Ninjaguy169 said: Multimap<Attribute, AttributeModifier> attributeModifiers = ArrayListMultimap.create(); attributeModifiers = builder.build(); this is completely unnecessary, why did you not return ImmutableMultimap.Builder#build Edited April 18, 20223 yr by Luis_ST
May 19, 20223 yr Hello, I also want to increase the reach attack of some tools. I would like you to help me especially with the PacketHandler and put it in the tools
May 19, 20223 yr 12 hours ago, Sokoly_ said: Hello, I also want to increase the reach attack of some tools. then read the posts before there is a solution 12 hours ago, Sokoly_ said: I would like you to help me especially with the PacketHandler and put it in the tools what did you mean by "PacketHandler and put it in the tools"?
August 7, 20223 yr Author Woah, this is pretty old and it hasn't been closed, so I may as well shove my solution in here. You instantiate a new Lazy, create a new ImmutableMultimap.Builder<Attribute, AttributeModifier> , shove your attributes alongside their modified values into that map, and return that map inside the Lazy. Afterwards (this is what I personally did), override the 'onEntitySwing' method in your item class. Get the player's eye position and check where they're looking. Get the distance (squared) between the attacker and the target. If the distance is close enough to where you can reach the target with your weapon/item, hurt the target. I feel like my explanation isn't that clear, so to make up for my lack of better wording, I made an example item class for anyone reading to follow: public class ExampleReachItem extends SwordItem { public static final UUID REACH_MOD = UUID.fromString("dccd59ec-6391-436d-9e00-47f2e6005e20"); //A randomly generated version 4 UUID public static final UUID KNOCKBACK_MOD = UUID.fromString("15bf6a06-b73b-4d8e-946a-61f63e1ba01e"); //Another randomly generated version 4 UUID public static double reach; public static double knockBack; public static int damage; public static int attackSpd; public static Lazy<? extends Multimap<Attribute, AttributeModifier>> ATTRIBUTE_LAZY_MAP = Lazy.of(() -> { Multimap<Attribute, AttributeModifier> map; ImmutableMultimap.Builder<Attribute, AttributeModifier> builder = ImmutableMultimap.builder(); builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Weapon modifier", damage, AttributeModifier.Operation.ADDITION)); builder.put(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_UUID, "Weapon modifier", attackSpd, AttributeModifier.Operation.ADDITION)); //Checking if the Forge 'Reach' Attribute is present if (ForgeMod.REACH_DISTANCE.isPresent()) { builder.put(ForgeMod.REACH_DISTANCE.get(), new AttributeModifier(REACH_MOD, "Weapon modifier", reach, AttributeModifier.Operation.ADDITION)); } builder.put(Attributes.ATTACK_KNOCKBACK, new AttributeModifier(KNOCKBACK_MOD, "Weapon modifier", knockBack, AttributeModifier.Operation.ADDITION)); map = builder.build(); return map; }); //Now you can modify the reach value and other attribute values per entry public ExampleReachItem(IItemTier tier, int dmg, float atkspd, double reach, double kb, Properties properties) { super(tier, dmg, atkspd, properties); this.damage = (int) ((float)dmg + tier.getAttackDamageBonus()); this.attackSpd = (int) atkspd; this.reach = reach; this.knockBack = kb; } @Override public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack) { return slot == EquipmentSlotType.MAINHAND ? ATTRIBUTE_LAZY_MAP.get() : super.getAttributeModifiers(slot, stack); } //This also works on blocks btw @Override public boolean onEntitySwing(ItemStack stack, LivingEntity entity) { double reach = entity.getAttributeValue(ForgeMod.REACH_DISTANCE.get()); double reachSqr = reach * reach; World world = entity.level; Vector3d viewVec = entity.getViewVector(1.0F); Vector3d eyeVec = entity.getEyePosition(1.0F); Vector3d targetVec = eyeVec.add(viewVec.x * reach, viewVec.y * reach, viewVec.z * reach); //Expanding the attacker's bounding box by the view vector's scale, and inflating it by 4.0D (x, y, z) AxisAlignedBB viewBB = entity.getBoundingBox().expandTowards(viewVec.scale(reach)).inflate(4.0D, 4.0D, 4.0D); EntityRayTraceResult result = ProjectileHelper.getEntityHitResult(world, entity, eyeVec, targetVec, viewBB, EntityPredicates.NO_CREATIVE_OR_SPECTATOR); if (result == null || !(result.getEntity() instanceof LivingEntity)) return false; LivingEntity target = (LivingEntity) result.getEntity(); double distanceToTargetSqr = entity.distanceToSqr(target); boolean hitResult = (result != null ? target : null) != null; if (hitResult) { if (entity instanceof PlayerEntity) { if (reachSqr >= distanceToTargetSqr) { target.hurt(DamageSource.playerAttack((PlayerEntity) entity), attackDamage); //Do stuff } } } return super.onEntitySwing(stack, entity); } } I'm bad at explaining stuff, so I apologize if I'm at any point unclear. I hope this helps anybody having the same issue, or a similar issue of some sort. Edit: The variables above the constructor don't have to be static, but they can be static. Me making them static was just force of habit XD. It was also a fault on my end for calling them in a non-static context inside my constructor. Edited August 7, 20223 yr by Ninjaguy169
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.