Jump to content

[1.12.2] [SOLVED] Don't spawn certain VillagerProfession in villages


Recommended Posts

Posted (edited)

Hey guys! This is my first topic here, although I am a frequent visitor, so at first i would like to say hello to all of you:) I'm sorry if anything below is not understandable, but im not native speaker and i don't have a lot occasions to write something in english.

 

Today i have faced a serious obstacle which i can't work around by myself. I'm working on a mod where i have added few custom VillageProfessions. I would like these custom villagers to be spawned in world only when player uses a special item on regular villager, which i had already implemented. The issue is that my custom villagers aslo spawn on world generation in regular villages, because of the VillagerRegistery.setRandomProfession() method. (i believe that it could be the problem)

 

I'v tried using Events like LivingSpawnEvent.CheckSpawn and LivingSpawnEvent.SpecialSpawn to check if the spawned entity is one of my custom villagers, and if so then replace it with another one with profession 5(nitwit), but it seems that that events are not fired when villagers are being spawned in villages.

Then I'v tried to add a custom capability to EntityVillager, which contained a single boolean field canSpawn intialized as false, and then i wanted to use it in EntityJoinWorldEvent becouse i figured out that this event was fired on villagers spawn (wow...who would have thought)

@SubscribeEvent
  public void entityJoinWorldEvent(EntityJoinWorldEvent event)
  {
    if(event.getEntity() instanceof EntityVillager)
    {
      EntityVillager villager = (EntityVillager) event.getEntity();
      ICanSpawn canSpawn = villager.getCapability(CanSpawnProvider.CANSPAWN,null);
      if(canSpawn.getCanSpawn() == false)//Fellow line 61 from stacktrace
      {
        //this checks if the joining villager profession is in arraylist of my custom professions
        if(CustomVillagerUtils.contains(villager.getProfessionForge()))
        {
          event.setCanceled(true);
          EntityVillager replacementVillager = new EntityVillager(event.getWorld(),5);
          replacementVillager.setPosition(villager.posX, villager.posY, villager.posZ);
          event.getWorld().spawnEntity(replacementVillager);
          System.out.println("Canceled spawning CUSTOMVILLAGER - Added NITWIT instead");
        }
      }
      //else if canSpawn == true, then spawn villager with my custom profession
    }
  }

And this is called when item is being used on EntityVillager:

public static void tryOutTheVillager(EntityPlayer player, EntityVillager target)
  {
    if (isValidForTransformation(target))
    {
      ICanSpawn canSpawn = player.getCapability(CanSpawnProvider.CANSPAWN, null);
      canSpawn.setCanSpawn(true); //this line also was generating NullPointerException

      turnVillagerIntoCustomVillager(player, target); //this just replaces current villager with a new custom one
//      canSpawn.setCanSpawn(false);
    }

  }

But this was a huge failure (i think that i didnt assigned the capability to the EntityVillager properly, and the entities cant see it, but i really dont know - today was my 1rst attempt on adding capabilites and i didnt figured out how does them work yet)

[01:13:42] [Server thread/ERROR] [FML]: Exception caught during firing event net.minecraftforge.event.entity.EntityJoinWorldEvent@6fec275d:
java.lang.NullPointerException: null
	at com.johny12340.customvillagers.common.util.handlers.EventHandler.entityJoinWorldEvent(EventHandler.java:61) ~[EventHandler.class:?]
	at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_20_EventHandler_entityJoinWorldEvent_EntityJoinWorldEvent.invoke(.dynamic) ~[?:?]
	at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?]
	at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:182) [EventBus.class:?]
	at net.minecraft.world.World.spawnEntity(World.java:1313) [World.class:?]
	at net.minecraft.world.WorldServer.spawnEntity(WorldServer.java:1121) [WorldServer.class:?]
	at net.minecraft.world.gen.structure.StructureVillagePieces$Village.spawnVillagers(StructureVillagePieces.java:1899) [StructureVillagePieces$Village.class:?]
	at net.minecraft.world.gen.structure.StructureVillagePieces$House4Garden.addComponentParts(StructureVillagePieces.java:1394) [StructureVillagePieces$House4Garden.class:?]
	at net.minecraft.world.gen.structure.StructureStart.generateStructure(StructureStart.java:51) [StructureStart.class:?]
	at net.minecraft.world.gen.structure.MapGenStructure.generateStructure(MapGenStructure.java:102) [MapGenStructure.class:?]
	at net.minecraft.world.gen.ChunkGeneratorOverworld.populate(ChunkGeneratorOverworld.java:412) [ChunkGeneratorOverworld.class:?]
	at net.minecraft.world.chunk.Chunk.populate(Chunk.java:1094) [Chunk.class:?]
	at net.minecraft.world.chunk.Chunk.populate(Chunk.java:1074) [Chunk.class:?]
	at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:169) [ChunkProviderServer.class:?]
	at net.minecraft.server.MinecraftServer.initialWorldChunkLoad(MinecraftServer.java:383) [MinecraftServer.class:?]
	at net.minecraft.server.integrated.IntegratedServer.loadAllWorlds(IntegratedServer.java:143) [IntegratedServer.class:?]
	at net.minecraft.server.integrated.IntegratedServer.init(IntegratedServer.java:160) [IntegratedServer.class:?]
	at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:552) [MinecraftServer.class:?]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_192]

 

Is there any other way to do this you guys can think of, or you can see what im missing in my previous attemps? I was thinking on some way to Override the vanilla VillagerRegistery.setRandomProfession() or use the InitMapGenEvent but dunno how for now.

WASABI-FINAL-THUMB.thumb.jpg.e3f7d6827611679b334177e9b0cfa5ca.jpg

 

 

 Aslo i will attach my capabilities code here, so maybe someone can tell me what i am doing wrong ;-;

ICanSpawn

public interface ICanSpawn 
{
  boolean getCanSpawn();
  void setCanSpawn(boolean canSpawn);
}

CanSpawn

public class CanSpawn implements ICanSpawn
{
  private boolean canSpawn;

  public CanSpawn() 
  {
    this.canSpawn = false;
  }
  @Override
  public boolean getCanSpawn()
  {
    System.out.println("getCanSpawn:"+canSpawn);
    return this.canSpawn;
  }

  @Override
  public void setCanSpawn(boolean canSpawn) 
  {
    this.canSpawn = canSpawn;
  }
}

CanSpawnStorage

public class CanSpawnStorage implements IStorage<ICanSpawn> 
  {
  @Nullable
  @Override
  public NBTBase writeNBT(Capability<ICanSpawn> capability, ICanSpawn instance, EnumFacing side)
  {
    NBTTagCompound tags = new NBTTagCompound();
    tags.setBoolean("canspawn", instance.getCanSpawn());
    return tags;
  }

  @Override
  public void readNBT(Capability<ICanSpawn> capability, ICanSpawn instance, EnumFacing side, NBTBase nbt)
  {
    NBTTagCompound tags = (NBTTagCompound) nbt;
    if (tags.hasKey("canspawn")) {
      instance.setCanSpawn(tags.getBoolean("canspawn"));
    }
  }
}

CanSpawnProvider

public class CanSpawnProvider implements ICapabilitySerializable<NBTTagCompound> //I was using ICapabilityProvider before (cuz i thought that this needn't to be serialized)
{
  @CapabilityInject(ICanSpawn.class)
  public final static Capability<ICanSpawn> CANSPAWN = null;

  private ICanSpawn instance = CANSPAWN.getDefaultInstance();

  @Override
  public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing)
  {
    System.out.println("hasCapability:"+CANSPAWN.getName());
    return capability == CANSPAWN;
  }

  @Nullable
  @Override
  public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
  {
    System.out.println("getCapability:"+CANSPAWN.getName());
    if (CANSPAWN != null && CANSPAWN == capability)
      return (T) instance;
    return null;
  }

  @Override
  public NBTTagCompound serializeNBT() 
  {
    return (NBTTagCompound) CANSPAWN.getStorage().writeNBT(CANSPAWN, instance, null);
  }

  @Override
  public void deserializeNBT(NBTTagCompound nbt) 
  {
    CANSPAWN.getStorage().readNBT(CANSPAWN, instance, null, nbt);
  }
}

CanSpawnFactory

public class CanSpawnFactory implements Callable<ICanSpawn>
{
  @Override
  public ICanSpawn call() throws Exception
  {
    return new CanSpawn();
  }
}

 

This is being called in my CommonProxy.preInit method:

CapabilityManager.INSTANCE.register(ICanSpawn.class, new CanSpawnStorage(), new CanSpawnFactory());

 

And here i'm attaching the capability to EntityVillager

public class CapabilityHandler
{
  public static final ResourceLocation CANSPAWN = new ResourceLocation(CustomVillagers.MODID, "canspawn");

  @SubscribeEvent
  public void attachCapability(AttachCapabilitiesEvent<Entity> event)
  {
    if (!(event.getObject() instanceof EntityVillager)) return;
    event.addCapability(CANSPAWN, new CanSpawnProvider());
  }
}

 

Oh f**k nvm, i have worked it around by myself... i didnt registered the CapabilityHandler, thats why it was throwing the NullPointerException at me. Still did not tested if the capability changes and if this method even work, but i will do it tomorow cuz im falling asleep now ?  I will update the post then.

 

Since I've already pasted all this here i will publish it, so maybe it will help someone, and maybe someone will look throught/review my code and tell me what i have done wrong and what i can improve. (also still maybe there is a better way of achieving the main goal -preventing the custom villagers from spawning- which i can't think of now)

 

SOLUTION

You can check how i solved this problem here: GitHub (It's a silly mod which im making to have fun with friends on server)

Basicly its the same way as before (Custom Capability and EntityJoinWorldEvent) but i did some improvements.

 

Edited by Johny1234
SOLVED
  • Like 1
Posted

I know you've solved this, but

48 minutes ago, Johny1234 said:

I'v tried using Events like LivingSpawnEvent.CheckSpawn and LivingSpawnEvent.SpecialSpawn

You could use the EntityJoinWorldEvent.

 

Posted

Can you post your code as a GitHub repository? It will save you from losing your work if you accidentally delete your entire project (this is actually relatively common) and will allow other people to view and review your code

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted
8 minutes ago, V0idWa1k3r said:

I know you've solved this, but

You could use the EntityJoinWorldEvent.

 

Hey, thanks for answer :) 

I couldn't fall asleep and have figured it out all now. It seems to work as intended. (Im using that custom capability and EntityJoinWorldEvent ;))

12 minutes ago, Cadiboo said:

Can you post your code as a GitHub repository? It will save you from losing your work if you accidentally delete your entire project (this is actually relatively common) and will allow other people to view and review your code

Thank you for advice, i will put it on GitHub and link it here tommorow! Actually it will be helpful becouse im deleteing bits of my code all the time, and next day i realise i could use that for something else?

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.