Jump to content

[1.18.1] [HELP] Mob Creation


LVUM

Recommended Posts

Just to be clear, my goal here is not to ask for written code.

I started "modding" a week ago, I already made some blocks, items, features and placements... (the very basic stuff).  I found McJty tutorials really helpfull in understanding minecraft system, forge library, and how to structure my project.

I would like to implement a mob in 1.18.1, but I cant seem to find any documentations or good tutorials on how to approach that... I have been using https://nekoyue.github.io/ documentation most of the time.

I would really appreciate some sort of guidance to how mobs are registered, how to create their AI, the conventions of creating a mob, etc...

  • Like 1
Link to comment
Share on other sites

it's true there isn't much - i struggled a lot too recently.

but lack of documentation isn't your first problem, it's the order of things. i assume you're making the armor stand mimic as mentioned in the other thread?

ok, order of things first...

1) stop writing behavior code until you have your creature on screen. start from scratch.
2) make a class extending zombie entity (for now). i'd even stick with it - zombies can wear armor, have two arms and legs (you'll make them thinner), have walk animation...
3) make a renderer class. if you're retexturing a zombie, you override getTextureLocation and done. or you can use it to replace the model and support the new one.
4) make a spawn egg. do not postpone this, you need to see the thingy on screen. see ForgeSpawnEgg class. (it doesn't exist in 1.16, make a manual/fake spawn egg, you need it asap)
5) you need some registration code. i'll just dump some, it's not something i can explain. (code is for 1.16 but should be ok in 1.18) i hold all of this in one class, you don't have to...
 

Spoiler
public class RegistrationManager
{
	private static final DeferredRegister<EntityType<?>> ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITIES, YourMod.MODID);
	private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, PeacefulMod.MODID);

	public static void init()
	{
		ENTITIES.register(FMLJavaModLoadingContext.get().getModEventBus());
		ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
	}

	public static final RegistryObject<EntityType<YourEntity>> ASDF = ENTITIES.register("your_creatures_string_id", () -> EntityType.Builder.<YourEntity>of(YourEntity::new, EntityClassification.CREATURE)
			.sized(0.6F, 1.95F)
			.clientTrackingRange(10)
			.setShouldReceiveVelocityUpdates(false)
			.build("your_creatures_string_id"));


	@ObjectHolder(YourMod.MODID + ":" + "your_creatures_string_id")
	public static EntityType<YourEntity> ASDF_HOLDER;

	@ObjectHolder(YourMod.MODID + ":" + "asdf_egg")
	public static SpawnEggItem ASDF_EGG;
}

again, this is just how i did it. no guarantees or refunds.

6) make a class for client-only initialization. subscribe to FMLClientSetupEvent and in the handler register your renderer: RenderingRegistry.registerEntityRenderingHandler(RegistrationManager.YOURTHINGY.get(), YourThingyRenderer::new);
6b) in 1.16 you may want to also subscribe to ColorHandlerEvent.Item event and color your spawn egg, if you created it manually.
6c) if Mod.EventBusSubscriber annotation has side parameter, (maybe it's called value), set it to client. otherwise (may depend on game version, not sure) make a new class that has a method that registers class from #6 to a given IEventBus; call that through DistExecutor.safeRunWhenOn in the constructor of your main mod class.
7) almost there... in the constructor of your main mod class activate the stuff from #5.
8] in your main mod class handle EntityAttributeCreationEvent. i may be doing it wrongly - feels wrong to me - but just do as i did because i lost a lot of time until i figured it... if i'm totally wrong about implementing this part, i apologize to whoever was sneezing because of the foul language i was tossing his way. event handler contents: event.put(RegistrationManager.YOUR_THINGY.get(), YourThingyEntity.createAttributes().build()); make createAttributes method in your entity class, copy from most similar vanilla entity (find method with that name).

ok, stop and don't proceed until you have a working spawn egg and entity that shows up when you use the egg.

  • Like 1
Link to comment
Share on other sites

now's the time for behavior, details like hitbox (hitbox is in registration manager), etc.

...

19a) if you want natural spawning, part one: in main mod class, in FMLCommonSetupEvent handler, try something like this:
event.enqueueWork(()-> EntitySpawnPlacementRegistry.register(RegistrationManager.WHATEVER.get(), EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, YourEntity::checkYourEntitySpawnRules));
19b) if you want natural spawning, part two: in another class (i have a dedicated one for this) subscribe to BiomeLoadingEvent. sample code:
 

Spoiler
		if (event.getCategory() == Biome.Category.YOUR_CONDITION_HERE)
		{
			event.getSpawns().getSpawner(EntityClassification.CREATURE).add(new MobSpawnInfo.Spawners(RegistrationManager.YOURTHINGY.get(), 12, 1, 4));
		}

remember to pick a proper classification. note that we stated the classification in two places, make sure they match.
19c) when seeing whether spawning works, don't be afraid to temporarily subscribe to "entity joins world" event and plop a block of glowstone at x,y+20,z. your time matters. also remember the locate biome command; it can teleport you.
20) for new/unique models, try blockbench. minor changes to existing models can be done in ide (extend model class).

Edited by MFMods
moved numbers
  • Like 1
Link to comment
Share on other sites

On 12/23/2021 at 6:19 PM, MFMods said:

6) make a class for client-only initialization. subscribe to FMLClientSetupEvent and in the handler register your renderer: RenderingRegistry.registerEntityRenderingHandler(RegistrationManager.YOURTHINGY.get(), YourThingyRenderer::new);

Just a question, is RenderingRegistry a class you created? Or are you using different mappings than the 1.18.1 official? I've used your tips so far and they've been pretty helpful, but I'm pretty stuck here (still somewhat unfamiliar with Forge/MC libraries)

  • Like 1
Link to comment
Share on other sites

Wow, thank you soo much!! I ended up managing to create my mob, register it, render it, create its egg etc etc. 

 

I was going to open another thread but since we are here (and the topic fits) I would like to ask how could you 

find non-living entities. I know you can get the nearest living entity like this:

this.mob.level.getNearestEntity(this.mob.level.getEntitiesOfClass(this.targetType, this.getTargetSearchArea(this.getFollowDistance()), (e) -> {return true;}), this.targetConditions, this.mob, this.mob.getX(), this.mob.getEyeY(), this.mob.getZ()));

But thats only for living creatures.

 

The mob (Animated Armor) should be a "floating armor" that attacks players if they are close and if not, then return to their armor standing. If its armor standing is destroyed, it should find the nearest armor standing.

 

Also...

The armor layer should be "bigger" than the skin, but for some reason (maybe the copy paste from piglins code), mine isnt.

public class AnimatedArmorRenderer extends HumanoidMobRenderer<AnimatedArmor, AnimatedArmorModel> {
    private static final ResourceLocation TEXTURE = new ResourceLocation(Rift.MODID, "textures/entity/animated_armor.png");

    public AnimatedArmorRenderer (EntityRendererProvider.Context context)
    {
        super(context, new AnimatedArmorModel(context.bakeLayer(AnimatedArmorModel.ANIMATED_ARMOR_LAYER)), 0f);
        this.addLayer(new HumanoidArmorLayer<>(this, new HumanoidModel(context.bakeLayer(AnimatedArmorModel.ANIMATED_ARMOR_LAYER)), new HumanoidModel(context.bakeLayer(AnimatedArmorModel.ANIMATED_ARMOR_LAYER))));
    }

    @Nonnull
    @Override
    public ResourceLocation getTextureLocation (AnimatedArmor entity)
    {
        return TEXTURE;
    }
}

 

As I said I dont like asking people for code, but god... I have spent maaaaanyy hours looking for documentation, comparing vanilla code, etc... and not much progress was done. 

 

One last question, where did you learn all that? Experience I guess (?)

  • Like 1
Link to comment
Share on other sites

update from 1.16 to 1.18:
instructions above work line-for-line, with no semantic changes. the dialect has changed however. in addition to common changes (level instead of world, etc.), here's a list of things you need to change that are related to making and registering a simple entity:

instead of Biome.Category.SWAMP  write  Biome.BiomeCategory.SWAMP
instead of EntityClassification.CREATURE write  MobCategory.CREATURE
instead of MobSpawnInfo.Spawners  write  MobSpawnSettings.SpawnerData
instead of EntityPredicate  use  TargetingConditions
instead of DataParameter/EntityDataManager/DataSerializers  write  EntityDataAccessor/SynchedEntityData/EntityDataSerializers
instead of IParticleData  write  ParticleOptions
instead of AttributeModifierMap.MutableAttribute  write  AttributeSupplier.Builder
instead of SpawnReason  write  MobSpawnType
instead of ILivingEntityData  write  SpawnGroupData
instead of MovementController  write  MoveControl
instead of WorldEntitySpawner  write  NaturalSpawner
instead of EntitySpawnPlacementRegistry.PlacementType  write  SpawnPlacements.Type
instead of RenderingRegistry.registerEntityRenderingHandler  write  EntityRenderers.register

 

 

  • Like 2
Link to comment
Share on other sites

3 hours ago, LVUM said:

The mob (Animated Armor) should be a "floating armor" that attacks players if they are close and if not, then return to their armor standing. If its armor standing is destroyed, it should find the nearest armor standing.

why don't you make an invisible floating zombie and just give it armor as equipment? that way you render a trivial entity (invisible one), game takes care of armor with support for any armor.

you don't need a second entity, just use existing armor stand and have your ghost remember its "home" stand. when the player destroys the armor stand (handle usual event), kill the ghost or assign it to another armor stand, whatever. good thing to note is that you can precisely control which armor parts equipped creature drops and with which chances.

when passive, set its location and rotation to that of the armor stand. have it attack and go back. change hitbox (size) to make it an actual ghost.

  • Like 1
Link to comment
Share on other sites

14 hours ago, MFMods said:

why don't you make an invisible floating zombie and just give it armor as equipment? that way you render a trivial entity (invisible one), game takes care of armor with support for any armor.

you don't need a second entity, just use existing armor stand and have your ghost remember its "home" stand. when the player destroys the armor stand (handle usual event), kill the ghost or assign it to another armor stand, whatever. good thing to note is that you can precisely control which armor parts equipped creature drops and with which chances.

when passive, set its location and rotation to that of the armor stand. have it attack and go back. change hitbox (size) to make it an actual ghost.

Still, how could I find the nearest Armor Standing (a non living entity) ?

  • Like 1
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.



×
×
  • Create New...

Important Information

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