Jump to content

Custom Entity spawns as a Pig


_vertig0

Recommended Posts

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 :)

Edited by _vertig0
Link to comment
Share on other sites

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.

Edited by [NoOneButNo]
Link to comment
Share on other sites

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!

Edited by _vertig0
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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 :/

Edited by _vertig0
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Edited by [NoOneButNo]
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

On 6/21/2020 at 1:47 PM, _vertig0 said:

Villagers spawned with other means

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.

Link to comment
Share on other sites

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 ;-;

Link to comment
Share on other sites

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



×
×
  • Create New...

Important Information

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