Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

_vertig0

Members
  • Posts

    45
  • Joined

  • Last visited

Posts posted by _vertig0

  1. 3 hours ago, thomask said:

     

    Hey, I was originally following a tutorial for my mod which registered the bow item like this 

    
    public class RegistryHandler {
    
        public static final DeferredRegister<Item> ITEMS = new DeferredRegister<>(ForgeRegistries.ITEMS, Megumin.MOD_ID);
    
        public static void init() {
            ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
        }
    
        // Items
        public static final RegistryObject<Item> STAFF = ITEMS.register("explosion_staff", ExplosionStaff::new);
    
    }

    Do i need both of these?

    When I inserted your code into my main class along with what i already have (above code), I got this error https://pastebin.com/47ag730Q

    The interesting part seems to be this

    
    [23:46:22] [Server-Worker-3/WARN] [ne.mi.re.ForgeRegistry/REGISTRIES]: Registry Item: Override did not have an associated owner object. Name: megumin:explosion_staff Value: air

     

    Also, when I delete my registry handler and just use your thing, it's just the same problem as before. The same debug messages print, but no arrow.

    Oh, my bad. I didn't realise you already registered your Bow. You're registering it correctly, ignore what I said

  2. 1 hour ago, thomask said:

    Hey guys, I am trying to make a projectile that extends off of ArrowEntity fire from my item based off of BowEntity. Here is my code for the Bow-based item:

    
    public class ExplosionStaff extends BowItem {
        public ExplosionStaff() {
            super(new Item.Properties().group(ItemGroup.COMBAT));
        }
    
        @Override
        public void onPlayerStoppedUsing(ItemStack stack, World worldIn, LivingEntity playerIn, int timeLeft) {
            ExplosionSpellEntity spell = new ExplosionSpellEntity(worldIn, playerIn);
            spell.shoot(playerIn, playerIn.rotationPitch, playerIn.rotationYaw, 0.0F, 50.0F, 0.0F);
            System.out.println("Debug: player stopped using staff");
        }
    
    }

     

    And here is the code for the arrow-based projectile:

     

    
    public class ExplosionSpellEntity extends ArrowEntity {
        public ExplosionSpellEntity(EntityType<? extends ArrowEntity> type, World worldIn) {
            super(type, worldIn);
        }
    
        public ExplosionSpellEntity(World worldIn, double x, double y, double z) {
            super(worldIn, x, y, z);
        }
    
        public ExplosionSpellEntity(World worldIn, LivingEntity shooter) {
            super(worldIn, shooter);
        }
    
        @Override
        public void shoot(Entity shooter, float pitch, float yaw, float p_184547_4_, float velocity, float inaccuracy) {
            float f = -MathHelper.sin(yaw * ((float)Math.PI / 180F)) * MathHelper.cos(pitch * ((float)Math.PI / 180F));
            float f1 = -MathHelper.sin(pitch * ((float)Math.PI / 180F));
            float f2 = MathHelper.cos(yaw * ((float)Math.PI / 180F)) * MathHelper.cos(pitch * ((float)Math.PI / 180F));
            this.shoot((double)f, (double)f1, (double)f2, velocity, inaccuracy);
            this.setMotion(this.getMotion().add(shooter.getMotion().x, shooter.onGround ? 0.0D : shooter.getMotion().y, shooter.getMotion().z));
            System.out.println("Debug: Shooted!!");
        }
    
        @Override
        public void onHit(RayTraceResult raytraceResultIn) {
            System.out.println("Debug: spell entity hit");
            this.world.createExplosion(this, this.getPosX(), this.getPosY(), this.getPosZ(), 20, false, Explosion.Mode.BREAK);
        }
    
    }

     

    As you can see, I put various debugging messages here. When I let go of the staff item, it displays the "Shooted!!" and "player stopped using staff" messages, but there is no arrow, so the onHit() debug doesn't print.

    What do i need to do? I couldn't find any tutorials on how to make projectiles for 1.15.2 so this is just my guess on where to start. I know I have to "register" entities but not sure how to do that. 

    Thank you!

    You actually don't need to register your arrow since it extends ArrowEntity, which causes Minecraft to treat it as a normal arrow but still execute your custom logic. You do however need to register your custom item. To do that you need to use Registry Events. Here's an example from my mod (This part goes inside your main class):

     

    @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
        public static class RegistryEvents {
            @SubscribeEvent
            public static void onItemRegistry(final RegistryEvent.Register<Item> event) {
              //This is how you register your Bow. However, in setRegistryName(), your mod should pass your own Mod ID for the first argument, not "minecraft". I'm only doing this in my mod because I'm overriding vanilla Bows. The second argument is whatever you name your custom Bow as. And to receive your Custom Bow you would do /give <your-name> modid:name-of-your-bow
                bow = new ItemForgeBow((new Item.Properties()).maxDamage(384).group(ItemGroup.COMBAT));
            	bow.setRegistryName("minecraft", "bow");
            	event.getRegistry().registerAll(bow);
            }
            
        }

    In any case, my mod does work and causes vanilla Bows to fire custom Arrows, so I'm confident that this is all you need for your special Bows to work

  3. 2 minutes ago, Alpvax said:

    Do you just mean with spawn eggs? Or do commands not work either?

    Vanilla spawn eggs (I believe) have the entity set when they are created, so if you override the entity, I think you also need to override the spawn egg to make it work.

    Disclaimer: I've not actually done it myself, but I believe that is the case.

    Villagers cured from Zombie Villagers also become Pigs sadly ;-;

  4. 3 hours ago, [NoOneButNo] said:

    Here's an example of how you override things:

     

    
    @ObjectHolder("minecraft:quick_charge")
    public static final Enchantment QUICK_CHARGE = null;
    
    
    @SubscribeEvent 
    public void onRegistry(RegistryEvent.Register<Enchantment> reg){
    
      //note: The class that you are using should be the one you made for the Enchantment Quickcharge. Enchantment class is an abstract class.
      reg.getRegistry().register(new Enchantment().setRegistryName(new ResourceLocation("minecraft", "quick_charge")));
    }

     

    Same thing applies for entity types, etc.

    Nope, didn't work either:

     

    [20:36:48] [Server thread/INFO] [mod.server.forge.ForgeServerCore/]: Spawn List Entry Removed: minecraft:pig*(1-1):5
    [20:36:48] [Server thread/INFO] [mod.server.forge.ForgeServerCore/]: Spawn List Entry Removed: minecraft:pig*(1-1):5
    [20:36:48] [Server thread/INFO] [mod.server.forge.ForgeServerCore/]: Spawn List Entry Removed: minecraft:pig*(1-1):5
    [20:36:48] [Server thread/INFO] [mod.server.forge.ForgeServerCore/]: Spawn List Entry Removed: minecraft:pig*(1-1):5
    
    

    (The console log is 100 lines long, I shortened it to 4 lines because every lines says the same thing)

    The above should be printing "Spawn List Entry Removed: minecraft:zombie_villager" if it had been successful

     

    Here's the updated code:

        // You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
        // Event bus for receiving Registry Events)
        @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
        public static class RegistryEvents {
            @SubscribeEvent
            public static void onBlocksRegistry(final RegistryEvent.Register<Block> blockRegistryEvent) {
                // register a new block here
                LOGGER.info("HELLO from Register Block");
                blockRegistryEvent.getRegistry().registerAll(new BlockSweetBerryBush(Block.Properties.create(Material.PLANTS).tickRandomly().doesNotBlockMovement().sound(SoundType.SWEET_BERRY_BUSH)).setRegistryName(new ResourceLocation("minecraft", "sweet_berry_bush")));
            }
            
            @SubscribeEvent
            public static void onItemRegistry(final RegistryEvent.Register<Item> event) {
            	event.getRegistry().registerAll(new ItemCrossbow((new Item.Properties()).maxStackSize(1).group(ItemGroup.COMBAT).maxDamage(397)).setRegistryName(new ResourceLocation("minecraft", "crossbow")), new ItemBow((new Item.Properties()).maxDamage(384).group(ItemGroup.COMBAT)).setRegistryName(new ResourceLocation("minecraft", "bow")));
            }
            
            @SubscribeEvent
            public static void onEntityRegistry(final RegistryEvent.Register<EntityType<?>> event) {
            	ResourceLocation villagerRegistry = new ResourceLocation("minecraft", "villager");
            	ResourceLocation zombieVillagerRegistry = new ResourceLocation("minecraft", "zombie_villager");
            	
            	event.getRegistry().registerAll(EntityType.Builder.<VillagerEntity>create(EntityVillager::new, EntityClassification.MISC).size(0.6F, 1.95F).build(villagerRegistry.toString()).setRegistryName(villagerRegistry), EntityType.Builder.create(EntityZombieVillager::new, EntityClassification.MONSTER).size(0.6F, 1.95F).immuneToFire().build(zombieVillagerRegistry.toString()).setRegistryName(zombieVillagerRegistry));
            }
            
            @SubscribeEvent
            public static void onEnchantRegistry(final RegistryEvent.Register<Enchantment> event) {
            	event.getRegistry().registerAll(new EnchantmentPiercing(Enchantment.Rarity.COMMON, EquipmentSlotType.MAINHAND).setRegistryName(new ResourceLocation("minecraft", "piercing")), new EnchantmentQuickCharge(Enchantment.Rarity.UNCOMMON, EquipmentSlotType.MAINHAND).setRegistryName(new ResourceLocation("minecraft", "quick_charge")));
            }
        }

    I even went into the game and grabbed a Villager Spawn egg just to check, and, you guessed it, it was a Pig making Villager noises

     

    I'm aware that the default Entity in the base vanilla code registers is a Pig, and Minecraft defaults to that if something goes wrong with registering the entity. But if that's the case, ALL Villagers in Minecraft should be Pigs, yet naturally spawning Villagers in my server (In Villages) are totally unaffected and have my custom traits, but Villagers spawned with other means are always Pigs

  5. 3 hours ago, [NoOneButNo] said:

    Here's an example of how you override things:

     

    
    @ObjectHolder("minecraft:quick_charge")
    public static final Enchantment QUICK_CHARGE = null;
    
    
    @SubscribeEvent 
    public void onRegistry(RegistryEvent.Register<Enchantment> reg){
    
      //note: The class that you are using should be the one you made for the Enchantment Quickcharge. Enchantment class is an abstract class.
      reg.getRegistry().register(new Enchantment().setRegistryName(new ResourceLocation("minecraft", "quick_charge")));
    }

     

    Same thing applies for entity types, etc.

    I'll give it a shot and let you know if it works for entities, thanks

     

    On a side note, is it ok to not put the variable and the ObjectHolder? I only stored the new overriding enchantments and stuff in a variable for debugging, my mod doesn't actually need it

  6. 1 hour ago, poopoodice said:

    What do you mean by "didn't work" ?

    By that I mean I'm still facing the original problem that caused me to post the thread. The Villager and Zombie Villager that I replaced are still spawning as pigs

     

    I'm starting to think this is a Forge Bug, since my code is exactly the same as all the tutorials I've followed so far

  7. I just checked out Choonster's mod in hopes of finding Entity registration code but unfortunately it uses the older system and can be used for 1.15.2 😧

     

    EDIT: Nevermind I'm blind I was looking at the 1.8 branch when there was a 1.14.4 branch *Facepalm

     

    EDIT 2: Choonster's code didn't work for me :/

  8. 2 hours ago, [NoOneButNo] said:

    I don't know why you have so many hacks set when its not even needed. You even overrided the vanilla enchantments and item wrong. take a look at choonster's github. https://github.com/Choonster-Minecraft-Mods/TestMod3/tree/1.14.4/src/main/java/choonster

    Oh, all the hack methods (Such as setFinalStatic and all that) were before I heard that the Forge registry allowed you to just plop your own replacements in. If that's what you meant you could safely ignore all the reflection in that class because I don't actually use those anymore

     

    If not I'm not too sure how because I registered the replacement items and enchantments following the tutorials online, through registry events. The Custom Items + the Enchantments also work as intended as well (Or at least haven't broken down yet, unlike the entities)

  9. Bump

     

    On 6/19/2020 at 2:32 PM, [NoOneButNo] said:

    I won't say its little cluttered, its damn as hell as cluttered as it can be. I will be analysing this but don't expect a fast reply soon.

    Should I reduce the code on Github to only include the part that is related to the issue, to save you the headache of searching through the monstrosity that is my mod's source code?

  10. 11 hours ago, [NoOneButNo] said:

    You are registering your entity types wrong. You don't initialize them via static intiializer. You use ObjectHolder (DeferredRegistry also works). Since you are OVERRIDING a vanilla entity, you match the object holder's string parameter with the desired minecraft id you want to override with.

    Nope, didn't work. They're still all Pigs

  11. 11 hours ago, [NoOneButNo] said:

    You are registering your entity types wrong. You don't initialize them via static intiializer. You use ObjectHolder (DeferredRegistry also works). Since you are OVERRIDING a vanilla entity, you match the object holder's string parameter with the desired minecraft id you want to override with.

    I could've sworn I wasn't using static initializers, since I only created the registry entries at the approriate registry event, and not within a static {} block. But anyway:

     

    I changed my registration to use the DeferredRegister, but now it keeps throwing these errors:

    238567078_2020-06-19(1).thumb.png.05a04dacfcc9bbe61df2b5348bd22e5e.png

    1658731348_2020-06-19(2).thumb.png.902b98e563e658c0a7cff9d24f9be7b3.png

    It's odd since EntityType.java is indeed the registry in vanilla Minecraft for Entities

     

    The full registry code:

    public static final DeferredRegister<EntityType> ENTITY_TYPES = new DeferredRegister<>(ForgeRegistries.ENTITIES, "minecraft");
    public static final RegistryObject<EntityType> VILLAGER = ENTITY_TYPES.register("villager", () -> EntityType.Builder.<EntityVillager>create(EntityVillager::new, EntityClassification.MISC).size(0.6F, 1.95F).build("villager"));
    public static final RegistryObject<EntityType> ZOMBIE_VILLAGER = ENTITY_TYPES.register("zombie_villager", () -> EntityType.Builder.<EntityZombieVillager>create(EntityZombieVillager::new, EntityClassification.MONSTER).size(0.6F, 1.95F).immuneToFire().build("zombie_villager"));
    
    public ForgeServerCore() {
        ENTITY_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());
        //All the other code here is not relevant so I removed it for brevity
    }


    EDIT: Solved the compile error, now I'm building the mod. Crossing my fingers and hope it works!

  12. I've been making a mod for my server and so far it's been going ok, but then I ran into this problem. I used the Registries to overwrite the vanilla Villager and Zombie Villager classes, but upon starting up my server I noticed a problem, I have code to remove Zombie Villagers from natural spawns in the ServerStarted block, normally it prints the debug message "Spawn List Entry minecraft:zombie_villager removed", but this time it printed "Spawn List Entry minecraft:pig removed". Completely confused, I went into my world and spawned a Zombie Villager with a spawn egg, and guess what? It wasn't a Zombie Villager at all, it was a Pig. I did the same thing with Villagers, and sure enough, they also spawned as pigs. They had Villager/Zombie Villager AI and sounds, but everything else, even their drops, were all characteristic of Pigs (They dropped Porkchops, sure enough). And looking further into my console, I also found the Villager death messages:

    [00:39:02] [Server thread/INFO] [minecraft/Entity]: Villager VillagerEntity['entity.minecraft.pig.cleric'/2298, l='world', x=-2046.59, y=106.41, z=1837.30] died, message: 'entity.minecraft.pig.cleric was slain by [Admin] _vertig0'
    [00:39:46] [Server thread/INFO] [minecraft/Entity]: Villager VillagerEntity['entity.minecraft.pig.armorer'/2448, l='world', x=-2034.57, y=107.05, z=1845.01] died, message: 'entity.minecraft.pig.armorer was slain by [Admin] _vertig0'
    [00:40:23] [Server thread/INFO] [minecraft/Entity]: Villager VillagerEntity['entity.minecraft.pig.none'/2487, l='world', x=-2032.48, y=105.00, z=1846.95] died, message: 'entity.minecraft.pig.none was slain by [Admin] _vertig0'
    

    entity.minecraft.pig.armourer?? Seriously?

    Edit: I just realised the above means the server is using the default Minecraft Villager class and not my class, since my class is named EntityVillager. VillagerEntity is the name of the Minecraft class

     

    And it gets even stranger. Zombie Villagers and Villagers spawned by the /summon command are perfectly normal, and render properly. Villagers that spawned naturally in the world before I loaded my updated mod were also fine. But any Villagers/Zombie Villagers that spawned after, unless spawned through /summon, are always Pigs...

     

    This is how I've overridden the vanilla classes, or at least tried to override. As far as I know I've done everything from the tutorials correctly (For setRegistryName the Mod ID is minecraft because I'm replacing vanilla classes):

    public static EntityType<?> villager;
    public static EntityType<?> zombieVillager;
    
    // You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
        // Event bus for receiving Registry Events)
        @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
        public static class RegistryEvents {
            
            @SubscribeEvent
            public static void onEntityRegistry(final RegistryEvent.Register<EntityType<?>> event) {
            	villager = EntityType.Builder.<EntityVillager>create(EntityVillager::new, EntityClassification.MISC).size(0.6F, 1.95F).build("villager").setRegistryName("minecraft", "villager");
            	zombieVillager = EntityType.Builder.<EntityZombieVillager>create(EntityZombieVillager::new, EntityClassification.MONSTER).size(0.6F, 1.95F).immuneToFire().build("zombie_villager").setRegistryName("minecraft", "zombie_villager");
            	event.getRegistry().registerAll(villager, zombieVillager);
            }
        }

    Could anyone help me out? I'm completely stumped by this issue. I've successfully overriden Items and Enchantments this way, but for some reason it just doesn't work with entities

     

    These here are my Custom Entity classes, I didn't change much, so I doubt this is the cause

    package mod.server.forgeservermod;
    
    import net.minecraft.entity.EntityType;
    import net.minecraft.entity.SharedMonsterAttributes;
    import net.minecraft.entity.effect.LightningBoltEntity;
    import net.minecraft.entity.merchant.villager.VillagerEntity;
    import net.minecraft.entity.villager.IVillagerType;
    import net.minecraft.world.GameRules;
    import net.minecraft.world.World;
    
    public class EntityVillager extends VillagerEntity {
    	
    	public EntityVillager(EntityType<? extends VillagerEntity> type, World worldIn) {
    	      super(type, worldIn);
    	}
    	
    	@Override
    	protected void registerAttributes() {
    		super.registerAttributes();
    		this.getAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(2.0D);
    		this.getAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).setBaseValue(1.0D);
    	}
    	
    	@Override
    	public void livingTick() {
    		if(this.world.getGameRules().getBoolean(GameRules.NATURAL_REGENERATION)) {
    			if (this.getHealth() < this.getMaxHealth() && this.ticksExisted % 20 == 0) {
    	            this.heal(2.0F);
    	         }
    		}
    		super.livingTick();
    	}
    	
    	public EntityVillager(EntityType<? extends VillagerEntity> type, World worldIn, IVillagerType villagerType) {
    		super(type, worldIn, villagerType);
    		// TODO Auto-generated constructor stub
    	}
    	
    	@Override
    	public void onStruckByLightning(LightningBoltEntity lightning) {
    		return;
    	}
    	
    	@Override
    	public boolean preventDespawn() {
    		return true;
    	}
    	
    }
    
    package mod.server.forgeservermod;
    
    import net.minecraft.entity.EntityType;
    import net.minecraft.entity.monster.ZombieVillagerEntity;
    import net.minecraft.world.World;
    
    public class EntityZombieVillager extends ZombieVillagerEntity {
    
    	public EntityZombieVillager(EntityType<? extends ZombieVillagerEntity> type, World world) {
    		super(type, world);
    		// TODO Auto-generated constructor stub
    	}
    	
    	@Override
    	public boolean preventDespawn() {
    		return true;
    	}
    	
    	@Override
    	public boolean canDespawn(double distanceToClosestPlayer) {
    		return false;
    	}
    
    }

    Thanks for taking the time to read my thread :)

  13. Right now I want to replace 2 Enchantments in Enchantments.java, VillagerEntity in EntityType.java and the Crossbow from Items.java to use my own items with custom logic, rather than the default vanilla logic. However, I can't seem to get past the public static final modifiers in said classes, even with reflection...

    Registering:

    // You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
        // Event bus for receiving Registry Events)
        @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
        public static class RegistryEvents {
            @SubscribeEvent
            public static void onBlocksRegistry(final RegistryEvent.Register<Block> blockRegistryEvent) {
                // register a new block here
                LOGGER.info("HELLO from Register Block");
                
            }
            
            @SubscribeEvent
            public static void onItemRegistry(final RegistryEvent.Register<Item> event) {
            	crossbow = new ItemForgeCrossbow((new Item.Properties()).maxStackSize(1).group(ItemGroup.COMBAT).maxDamage(326));
            	event.getRegistry().registerAll(crossbow.setRegistryName("crossbow"));
            	try {
    				ForgeServerCore.usetFinalStatic(ObfuscationReflectionHelper.findField(Items.class, "field_222114_py"), crossbow);
    			} catch (Exception exception) {
    				// TODO Auto-generated catch block
    				LOGGER.error("Error encountered while overwriting base Items.class fields");
    				exception.printStackTrace();
    			}
            }
            
            @SubscribeEvent
            public static void onEntityRegistry(final RegistryEvent.Register<EntityType<?>> event) {
            	EntityType<?> villager = EntityType.Builder.<EntityVillager>create(EntityVillager::new, EntityClassification.MISC).size(0.6F, 1.95F).build("villager").setRegistryName("villager");
            	event.getRegistry().registerAll(villager);
            	try {
    				ForgeServerCore.usetFinalStatic(ObfuscationReflectionHelper.findField(EntityType.class, "field_200756_av"), villager);
    			} catch (IllegalAccessException exception) {
    				// TODO Auto-generated catch block
    				exception.printStackTrace();
    			}
            }
            
            @SubscribeEvent
            public static void onEnchantRegistry(final RegistryEvent.Register<Enchantment> event) {
            	quickCharge = new CustomEnchantmentQuickCharge(Enchantment.Rarity.UNCOMMON, EquipmentSlotType.MAINHAND);
            	piercing = new CustomEnchantmentPiercing(Enchantment.Rarity.COMMON, EquipmentSlotType.MAINHAND);
            	event.getRegistry().registerAll(piercing.setRegistryName("piercing"), quickCharge.setRegistryName("quick_charge"));
            	try {
        			ForgeServerCore.usetFinalStatic(ObfuscationReflectionHelper.findField(Enchantments.class, "field_222193_H"), quickCharge);
        			ForgeServerCore.usetFinalStatic(ObfuscationReflectionHelper.findField(Enchantments.class, "field_222194_I"), piercing);
        		} catch (Exception exception) {
        			// TODO Auto-generated catch block
        			LOGGER.error("Error encountered while overwriting base Enchantments.class fields");
        			exception.printStackTrace();
        		}
            }
        }

    In case this is required, these are my custom classes with modified logic:

    Spoiler
    
    package mod.server.forgeservermod;
    
    import net.minecraft.entity.EntityType;
    import net.minecraft.entity.effect.LightningBoltEntity;
    import net.minecraft.entity.merchant.villager.VillagerEntity;
    import net.minecraft.entity.villager.IVillagerType;
    import net.minecraft.world.GameRules;
    import net.minecraft.world.World;
    
    public class EntityVillager extends VillagerEntity {
    	
    	public EntityVillager(EntityType<? extends VillagerEntity> type, World worldIn) {
    	      super(type, worldIn);
    	}
    	
    	@Override
    	public void livingTick() {
    		if(this.world.getGameRules().getBoolean(GameRules.NATURAL_REGENERATION)) {
    			if (this.getHealth() < this.getMaxHealth() && this.ticksExisted % 20 == 0) {
    	            this.heal(2.0F);
    	         }
    		}
    		super.livingTick();
    	}
    	
    	public EntityVillager(EntityType<? extends VillagerEntity> type, World worldIn, IVillagerType villagerType) {
    		super(type, worldIn, villagerType);
    		// TODO Auto-generated constructor stub
    	}
    	
    	@Override
    	public void onStruckByLightning(LightningBoltEntity lightning) {
    		this.getServer().logInfo(this.getName().getFormattedText() + ": Did you really think I was going to turn into a witch?");
    		return;
    	}
    	
    }
    
    package mod.server.forgeservermod;
    
    import java.util.List;
    import java.util.Random;
    
    import com.google.common.collect.Lists;
    
    import net.minecraft.advancements.CriteriaTriggers;
    import net.minecraft.client.renderer.Quaternion;
    import net.minecraft.client.renderer.Vector3f;
    import net.minecraft.enchantment.EnchantmentHelper;
    import net.minecraft.enchantment.Enchantments;
    import net.minecraft.entity.Entity;
    import net.minecraft.entity.ICrossbowUser;
    import net.minecraft.entity.IProjectile;
    import net.minecraft.entity.LivingEntity;
    import net.minecraft.entity.item.FireworkRocketEntity;
    import net.minecraft.entity.player.PlayerEntity;
    import net.minecraft.entity.player.ServerPlayerEntity;
    import net.minecraft.entity.projectile.AbstractArrowEntity;
    import net.minecraft.item.ArrowItem;
    import net.minecraft.item.CrossbowItem;
    import net.minecraft.item.Item;
    import net.minecraft.item.ItemStack;
    import net.minecraft.item.Items;
    import net.minecraft.nbt.CompoundNBT;
    import net.minecraft.nbt.ListNBT;
    import net.minecraft.stats.Stats;
    import net.minecraft.util.ActionResult;
    import net.minecraft.util.Hand;
    import net.minecraft.util.SoundCategory;
    import net.minecraft.util.SoundEvents;
    import net.minecraft.util.math.Vec3d;
    import net.minecraft.world.World;
    
    public class ItemForgeCrossbow extends CrossbowItem {
    	
    	public boolean isLoadingStart = false;
    	public boolean isLoadingMiddle = false;
    	
    	public ItemForgeCrossbow(Properties properties) {
    		super(properties);
    		// TODO Auto-generated constructor stub
    	}
    	
    	private static float func_220013_l(ItemStack p_220013_0_) {
    	      return p_220013_0_.getItem() == Items.CROSSBOW && hasChargedProjectile(p_220013_0_, Items.FIREWORK_ROCKET) ? 1.6F : 4.27F;
    	}
    	
    	@Override
    	public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
    	      ItemStack itemstack = playerIn.getHeldItem(handIn);
    	      if (isCharged(itemstack)) {
    	         fireProjectiles(worldIn, playerIn, handIn, itemstack, func_220013_l(itemstack), 1.0F);
    	         setCharged(itemstack, false);
    	         return ActionResult.resultSuccess(itemstack);
    	      } else if (!playerIn.findAmmo(itemstack).isEmpty()) {
    	         if (!isCharged(itemstack)) {
    	            this.isLoadingStart = false;
    	            this.isLoadingMiddle = false;
    	            playerIn.setActiveHand(handIn);
    	         }
    
    	         return ActionResult.resultConsume(itemstack);
    	      } else {
    	         return ActionResult.resultFail(itemstack);
    	      }
    	   }
    	
    	private static void fireProjectile(World worldIn, LivingEntity shooter, Hand handIn, ItemStack crossbow, ItemStack projectile, float soundPitch, boolean isCreativeMode, float velocity, float inaccuracy, float projectileAngle) {
    	      if (!worldIn.isRemote) {
    	         boolean flag = projectile.getItem() == Items.FIREWORK_ROCKET;
    	         IProjectile iprojectile;
    	         if (flag) {
    	            iprojectile = new FireworkRocketEntity(worldIn, projectile, shooter.getPosX(), shooter.getPosYEye() - (double)0.15F, shooter.getPosZ(), true);
    	         } else {
    	            iprojectile = createArrow(worldIn, shooter, crossbow, projectile);
    	            if (isCreativeMode || projectileAngle != 0.0F) {
    	               ((AbstractArrowEntity)iprojectile).pickupStatus = AbstractArrowEntity.PickupStatus.CREATIVE_ONLY;
    	            }
    	         }
    
    	         if (shooter instanceof ICrossbowUser) {
    	            ICrossbowUser icrossbowuser = (ICrossbowUser)shooter;
    	            icrossbowuser.shoot(icrossbowuser.getAttackTarget(), crossbow, iprojectile, projectileAngle);
    	         } else {
    	            Vec3d vec3d1 = shooter.getUpVector(1.0F);
    	            Quaternion quaternion = new Quaternion(new Vector3f(vec3d1), projectileAngle, true);
    	            Vec3d vec3d = shooter.getLook(1.0F);
    	            Vector3f vector3f = new Vector3f(vec3d);
    	            vector3f.transform(quaternion);
    	            iprojectile.shoot((double)vector3f.getX(), (double)vector3f.getY(), (double)vector3f.getZ(), velocity, inaccuracy);
    	         }
    
    	         crossbow.damageItem(flag ? 3 : 1, shooter, (p_220017_1_) -> {
    	            p_220017_1_.sendBreakAnimation(handIn);
    	         });
    	         worldIn.addEntity((Entity)iprojectile);
    	         worldIn.playSound((PlayerEntity)null, shooter.getPosX(), shooter.getPosY(), shooter.getPosZ(), SoundEvents.ITEM_CROSSBOW_SHOOT, SoundCategory.PLAYERS, 1.0F, soundPitch);
    	      }
    	   }
    
    	   private static AbstractArrowEntity createArrow(World worldIn, LivingEntity shooter, ItemStack crossbow, ItemStack ammo) {
    	      ArrowItem arrowitem = (ArrowItem)(ammo.getItem() instanceof ArrowItem ? ammo.getItem() : Items.ARROW);
    	      AbstractArrowEntity abstractarrowentity = arrowitem.createArrow(worldIn, ammo, shooter);
    	      
    	      abstractarrowentity.setIsCritical(true);
    	      abstractarrowentity.setDamage(5.0D);
    
    	      abstractarrowentity.setHitSound(SoundEvents.ITEM_CROSSBOW_HIT);
    	      abstractarrowentity.setShotFromCrossbow(true);
    	      int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.PIERCING, crossbow);
    	      if (i > 0) {
    	    	 abstractarrowentity.setKnockbackStrength(i);
    	         abstractarrowentity.setPierceLevel((byte)i);
    	         abstractarrowentity.setDamage(abstractarrowentity.getDamage() + i);
    	      }
    
    	      return abstractarrowentity;
    	   }
    	   
    	   private static List<ItemStack> getChargedProjectiles(ItemStack stack) {
    		      List<ItemStack> list = Lists.newArrayList();
    		      CompoundNBT compoundnbt = stack.getTag();
    		      if (compoundnbt != null && compoundnbt.contains("ChargedProjectiles", 9)) {
    		         ListNBT listnbt = compoundnbt.getList("ChargedProjectiles", 10);
    		         if (listnbt != null) {
    		            for(int i = 0; i < listnbt.size(); ++i) {
    		               CompoundNBT compoundnbt1 = listnbt.getCompound(i);
    		               list.add(ItemStack.read(compoundnbt1));
    		            }
    		         }
    		      }
    
    		      return list;
    		   }
    	   
    	   private static boolean hasChargedProjectile(ItemStack stack, Item ammoItem) {
    		      return getChargedProjectiles(stack).stream().anyMatch((p_220010_1_) -> {
    		         return p_220010_1_.getItem() == ammoItem;
    		      });
    		   }
    	   
    	   private static float[] getRandomSoundPitches(Random rand) {
    		      boolean flag = rand.nextBoolean();
    		      return new float[]{1.0F, getRandomSoundPitch(flag), getRandomSoundPitch(!flag)};
    		   }
    
    		   private static float getRandomSoundPitch(boolean flagIn) {
    		      float f = flagIn ? 0.63F : 0.43F;
    		      return 1.0F / (random.nextFloat() * 0.5F + 1.8F) + f;
    		   }
    	   
    	   public static void fireProjectiles(World worldIn, LivingEntity shooter, Hand handIn, ItemStack stack, float velocityIn, float inaccuracyIn) {
    	      List<ItemStack> list = getChargedProjectiles(stack);
    	      float[] afloat = getRandomSoundPitches(shooter.getRNG());
    
    	      for(int i = 0; i < list.size(); ++i) {
    	         ItemStack itemstack = list.get(i);
    	         boolean flag = shooter instanceof PlayerEntity && ((PlayerEntity)shooter).abilities.isCreativeMode;
    	         if (!itemstack.isEmpty()) {
    	            if (i == 0) {
    	               fireProjectile(worldIn, shooter, handIn, stack, itemstack, afloat[i], flag, velocityIn, 0.07F, 0.0F);
    	            } else if (i == 1) {
    	               fireProjectile(worldIn, shooter, handIn, stack, itemstack, afloat[i], flag, velocityIn, 0.07F, -10.0F);
    	            } else if (i == 2) {
    	               fireProjectile(worldIn, shooter, handIn, stack, itemstack, afloat[i], flag, velocityIn, 0.07F, 10.0F);
    	            }
    	         }
    	      }
    
    	      fireProjectilesAfter(worldIn, shooter, stack);
    	   }
    	   
    	   private static void fireProjectilesAfter(World worldIn, LivingEntity shooter, ItemStack stack) {
    		      if (shooter instanceof ServerPlayerEntity) {
    		         ServerPlayerEntity serverplayerentity = (ServerPlayerEntity)shooter;
    		         if (!worldIn.isRemote) {
    		            CriteriaTriggers.SHOT_CROSSBOW.func_215111_a(serverplayerentity, stack);
    		         }
    
    		         serverplayerentity.addStat(Stats.ITEM_USED.get(stack.getItem()));
    		      }
    
    		      clearProjectiles(stack);
    	   }
    	   
    	   private static void clearProjectiles(ItemStack stack) {
    		      CompoundNBT compoundnbt = stack.getTag();
    		      if (compoundnbt != null) {
    		         ListNBT listnbt = compoundnbt.getList("ChargedProjectiles", 9);
    		         listnbt.clear();
    		         compoundnbt.put("ChargedProjectiles", listnbt);
    		      }
    
    		   }
    
    }
    
    package mod.server.forgeservermod;
    
    import net.minecraft.enchantment.QuickChargeEnchantment;
    import net.minecraft.inventory.EquipmentSlotType;
    
    public class CustomEnchantmentQuickCharge extends QuickChargeEnchantment {
    
    	public CustomEnchantmentQuickCharge(Rarity rarity, EquipmentSlotType slotType) {
    		super(rarity, slotType);
    		// TODO Auto-generated constructor stub
    	}
    	
    	@Override
    	public int getMaxLevel() {
    		return 5;
    	}
    	
    }
    private static Unsafe unsafe;
    
    Field field = null;
    		try {
    			field = Unsafe.class.getDeclaredField("theUnsafe");
    		} catch (NoSuchFieldException exception) {
    			// TODO Auto-generated catch block
    			exception.printStackTrace();
    		} catch (SecurityException exception) {
    			// TODO Auto-generated catch block
    			exception.printStackTrace();
    		} //Internal reference
    		if(field == null) {
    			LOGGER.fatal("Field is null");
    		}
            field.setAccessible(true);
            try {
    			unsafe = (Unsafe) field.get(null);
    		} catch (IllegalArgumentException exception) {
    			// TODO Auto-generated catch block
    			exception.printStackTrace();
    		} catch (IllegalAccessException exception) {
    			// TODO Auto-generated catch block
    			exception.printStackTrace();
    		}
            
            if(unsafe == null) {
    			LOGGER.fatal("Unsafe is null");
    		}
    
    public static void usetFinalStatic(Field field, Object object) throws IllegalAccessException {
        	LOGGER.info("Original field value: " + field.get(null));
            //we need a field to update
            //this is a 'base'. Usually a Class object will be returned here.
            final Object base = unsafe.staticFieldBase(field);
            //this is an 'offset'
            final long offset = unsafe.staticFieldOffset(field);
            //actual update
            unsafe.putObject(base, offset, object);
            //ensure the value was updated
            LOGGER.info( "Updated static final value: " + field.get(null));
        }

    And this is how I'm trying to modify static final fields ^

     

    Why am I doing this? Because these are hardcoded variables stored in a class. Only other way is ASM

  14. 3 minutes ago, Novârch said:

    This doesn't seem like a good use case for ASM.

     

    Thing about this for a second, are arrows living? Of course they aren't, arrows extend Entity and implement IProjectile.

    In my opinion you should cancel one of the many events (maybe ArrowLooseEvent?) that references arrows and implement your own physics there.

    I'll try that and see if it works, but I suspect it's just going to clash with the base physics in AbstractArrowEntity anyway and go all wonky

     

     

    Ah well, who else to blame but Mojang haha

  15. Ok, I will preface this by saying I know ASM and coremods should only be used when absolutely necessary. I've been trying to remove air resistance from arrows on my server, and this pesky bit of code is always eluding me:

    float f2 = 0.99F;
    if (this.isInWater()) {
        for(int j = 0; j < 4; ++j) {
            float f4 = 0.25F;
            this.world.addParticle(ParticleTypes.BUBBLE, d5 - d3 * 0.25D, d1 - d4 * 0.25D, d2 - d0 * 0.25D, d3, d4, d0);
        }
    
        f2 = this.getWaterDrag();
    }
    
    this.setMotion(vec3d.scale((double)f2));

    float f2 is basically how drag is implemented in arrows. If I could simply delete the line f2 = this.getWaterDrag() and set float f2 = 1.0F, I'd have removed air resistance

     

    The problem is that the f2 variable isn't defined in the class, it's defined in the method block. Instantly that completely makes reflection useless. I can't replace AbstractArrowEntity.java with my own Arrow Entity either, because it's a base class diverging out to many different Arrow subclasses. If I did that the server would crash every time a tipped arrow was shot. And I've also tried reverting the drag using LivingUpdateEvent at both end and start phases, and even both phases at once, but all that did was make arrows unusable because they'd fly around randomly after being shot. It seems ASM is my only way forward unfortunately, but Forge has switched the Coremod system and I'm not too sure how to use it

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.