Jump to content

yeetsche420

Members
  • Posts

    18
  • Joined

  • Last visited

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

yeetsche420's Achievements

Tree Puncher

Tree Puncher (2/8)

0

Reputation

  1. I got it to work. Strangely, naming the file en_us.json instead of en_US.json fixed it. It seems Minecraft cares about the casing.
  2. When I publish my mod using the publish gradle script that comes with the forge mdk and use the resulting .jar file in my Minecraft mods, none of the objects I've added are named with the strings I provided in en_US.json. They all use the resource location as the name. I tried providing an en_US.lang as well, but that didn't help. Whenever I ran the mod in development using the runClient script from the mdk, all the items were named correctly. Why is this happening and how can I fix it?
  3. I figured it out. Having my mob entity inherit from PathfinderMob instead of Monster did the trick.
  4. I currently have the following spawn predicate set up for my mob: public static boolean checkMyMobSpawnRules(EntityType<? extends MyMob> entityType, ServerLevelAccessor serverLevelAccessor, MobSpawnType mobSpawnType, BlockPos blockPos, Random random) { boolean notUndergroundOrIndoors = true; for (int y = blockPos.getY() + 1; y < 320; ++y) { BlockState blockState = serverLevelAccessor.getBlockState(new BlockPos(blockPos.getX(), y, blockPos.getZ())); Block block = blockState.getBlock(); if (!(block instanceof AirBlock || block instanceof LeavesBlock)) { notUndergroundOrIndoors = false; break; } } return Monster.checkAnyLightMonsterSpawnRules(entityType, serverLevelAccessor, mobSpawnType, blockPos, random) && notUndergroundOrIndoors && Utils.nearbyChunkHasCrop(serverLevelAccessor, blockPos); } I have the following subscriber for a BiomeLoadingEvent: @SubscribeEvent(priority = EventPriority.HIGHEST) public static void biomeLoading(BiomeLoadingEvent event) { Biome.BiomeCategory category = event.getCategory(); if (category != Biome.BiomeCategory.NETHER && category != Biome.BiomeCategory.THEEND) { event.getSpawns().addSpawn(MobCategory.MONSTER, new MobSpawnSettings.SpawnerData(ModEntities.MY_MOB.get(), 100, 1, 1)); } } I also subscribe to FMLCommonSetupEvent: @SubscribeEvent public static void commonSetup(FMLCommonSetupEvent event) { event.enqueueWork(() -> SpawnPlacements.register(ModEntities.STALIN.get(), SpawnPlacements.Type.ON_GROUND, Heightmap.Types.WORLD_SURFACE, Stalin::checkStalinSpawnRules)); } My logic seems to be working with 1 exception: my mob only spawns at night. I thought using Monster.checkAnyLightMonsterSpawnRules would allow my mob to spawn day or night. Is there a way to get my mob to spawn at any time of day? My subclasses Monster if that's relevant.
  5. I managed to get something I like. Here's my code: MoveToCropGoal: public class MoveToCropGoal extends MoveToBlockGoal { private static final int GIVE_UP_TICKS = 600; private boolean shouldStop; private boolean isNearCrop; private int timesRun; public MoveToCropGoal(PathfinderMob mob) { super(mob, 1.0, 100, 20); timesRun = 0; } @Override protected boolean isValidTarget(LevelReader levelReader, BlockPos blockPos) { return levelReader.getBlockState(blockPos).getBlock() instanceof CropBlock; } @Override public boolean shouldRecalculatePath() { return this.tryTicks % 10 == 0; } @Override public void start() { super.start(); shouldStop = false; isNearCrop = true; ++timesRun; } @Override protected int nextStartTick(PathfinderMob pathfinderMob) { return (isNearCrop || timesRun == 0) ? 3 : super.nextStartTick(pathfinderMob); } @Override public void stop() { shouldStop = true; } @Override public boolean isInterruptable() { return false; } @Override protected boolean isReachedTarget() { return super.isReachedTarget() || Utils.getSurroundingBlockPoses(mob).stream().anyMatch(blockPos -> Utils.blockPosIsCrop(mob.level, blockPos)); } @Override public boolean canContinueToUse() { boolean canContinue = !shouldStop && !this.isReachedTarget() && tryTicks <= GIVE_UP_TICKS && isValidTarget(mob.level, blockPos); if (!canContinue) { isNearCrop = findNearestBlock(); } return canContinue; } } EatCropGoal: public class EatCropGoal extends EatBlockGoal { protected final Mob mob; protected final Level level; private final int MAX_TICKS = 10; private int ticks; private boolean hasEaten; public EatCropGoal(Mob mob) { super(mob); this.mob = mob; this.level = mob.level; } @Override public boolean canUse() { return Utils.getSurroundingBlockPoses(this.mob).stream() .anyMatch(blockPos -> Utils.blockPosIsCrop(this.level, blockPos)); } @Override public boolean canContinueToUse() { return !this.hasEaten && this.ticks < MAX_TICKS; } @Override public void start() { super.start(); this.ticks = 0; this.hasEaten = false; } @Override public boolean isInterruptable() { return false; } @Override public void stop() { this.hasEaten = true; } @Override public void tick() { ++this.ticks; if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { List<BlockPos> cropsToEat = Utils.getSurroundingBlockPoses(this.mob).stream() .filter(blockPos -> Utils.blockPosIsCrop(this.level, blockPos)).toList(); for (BlockPos cropToEat : cropsToEat) { this.level.destroyBlock(cropToEat, false); this.mob.ate(); this.mob.gameEvent(GameEvent.EAT, this.mob.eyeBlockPosition()); } if (cropsToEat.size() > 0) { this.hasEaten = true; } } } }
  6. Higher priority means passing a lower number to addGoal, right?
  7. I took a look at MoveToBlockGoal's canUse method and noticed that it has a nextStartTick that it uses in determining if it can be used. I'll try playing with that to see if it makes a difference.
  8. I'm currently making a mob that eats crops. I've got it kind of working, but the behavior isn't quite the way I want it to be. My goal is to get the mob to eat all crops nearby without stopping. Currently, my mob will move up to a crop, eat it, and then be idle for awhile as neither the move to crop goal nor eat crop goal are being started. Is there a way to get make these goals fire more often? MoveToCropGoal: public class MoveToCropGoal extends MoveToBlockGoal { private static final int GIVE_UP_TICKS = 600; private boolean shouldStop; public MoveToCropGoal(PathfinderMob mob) { super(mob, 1.0, 100); } @Override protected boolean isValidTarget(LevelReader levelReader, BlockPos blockPos) { return levelReader.getBlockState(blockPos).getBlock() instanceof CropBlock; } @Override public boolean shouldRecalculatePath() { return this.tryTicks % 10 == 0; } @Override public void start() { super.start(); Main.LOGGER.info("Starting to move towards crop"); shouldStop = false; } @Override public void stop() { this.shouldStop = true; } @Override protected boolean isReachedTarget() { return super.isReachedTarget() || Utils.getSurroundingBlockPoses(this.mob).stream().anyMatch(blockPos -> Utils.blockPosIsCrop(this.mob.level, blockPos)); } @Override public boolean canContinueToUse() { boolean canContinue = !shouldStop && !this.isReachedTarget() && this.tryTicks <= GIVE_UP_TICKS && this.isValidTarget(this.mob.level, this.blockPos); Main.LOGGER.info("Can continue to move towards crop: " + canContinue); return canContinue; } } EatCropGoal: public class EatCropGoal extends EatBlockGoal { protected final Mob mob; protected final Level level; private final int MAX_TICKS = 10; private int ticks; private boolean hasEaten; public EatCropGoal(Mob mob) { super(mob); this.mob = mob; this.level = mob.level; } @Override public boolean canUse() { for (BlockPos blockPos : Utils.getSurroundingBlockPoses(this.mob)) { if (Utils.blockPosIsCrop(this.level, blockPos)) { return true; } } return false; } @Override public boolean canContinueToUse() { return !this.hasEaten || this.ticks < MAX_TICKS; } @Override public void start() { super.start(); Main.LOGGER.info("Eating crops"); this.ticks = 0; this.hasEaten = false; } @Override public void stop() { this.hasEaten = true; } @Override public void tick() { ++this.ticks; List<BlockPos> cropsToEat = Utils.getSurroundingBlockPoses(this.mob).stream() .filter(blockPos -> Utils.blockPosIsCrop(this.level, blockPos)).toList(); if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { for (BlockPos cropToEat : cropsToEat) { this.level.destroyBlock(cropToEat, false); this.mob.ate(); this.mob.gameEvent(GameEvent.EAT, this.mob.eyeBlockPosition()); } if (cropsToEat.size() > 0) { this.hasEaten = true; } } } } registerGoals: @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); this.goalSelector.addGoal(15, new WaterAvoidingRandomStrollGoal(this, 1.0, 0f)); this.goalSelector.addGoal(1, new HurtByTargetGoal(this)); this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1d, false)); this.goalSelector.addGoal(2, new MoveToCropGoal(this)); this.goalSelector.addGoal(2, new EatCropGoal(this)); }
  9. Thanks for mentioning the renderer. Extending HumanoidMobRenderer worked since it has logic for rendering items in hands.
  10. That might be it. My Renderer currently extends MobRenderer. It looks like the following: public class MyMobRenderer<Type extends MyMob> extends MobRenderer<Type, MyMobModel<Type>> { private static final ResourceLocation TEXTURE = new ResourceLocation(Main.MOD_ID, "textures/entities/my_mob.png"); public MyMobRenderer(EntityRendererProvider.Context context) { super(context, new MyMobModel<>(context.bakeLayer(MyMobModel.LAYER_LOCATION)), 0.5f); } @Override public ResourceLocation getTextureLocation(MyMob entity) { return TEXTURE; } } I'll try extending HumanoidMobRenderer to see if that works.
  11. I'm not seeing the item in the mob's hand when it spawns.
  12. The method is called. I debugged the code when I used a spawn egg for my mob and stepped through the code, and it did call setItemSlot. I would hit the breakpoint in the debugger both using the spawn egg and using SpawnPlacements.register.
  13. Basically the title. For my mob class, I have the following 2 methods overridden: @Override protected void populateDefaultEquipmentSlots(DifficultyInstance difficultyInstance) { this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(ModItems.COMICALLY_LARGE_SPOON.get())); } @Nullable @Override public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverLevelAccessor, DifficultyInstance difficultyInstance, MobSpawnType mobSpawnType, @Nullable SpawnGroupData spawnGroupData, @Nullable CompoundTag compoundTag) { SpawnGroupData spawnGroupDataToReturn = super.finalizeSpawn(serverLevelAccessor, difficultyInstance, mobSpawnType, spawnGroupData, compoundTag); this.populateDefaultEquipmentSlots(difficultyInstance); return spawnGroupDataToReturn; } I've already tested the item separately, so I know it works fine. However, I still can't get my mob to spawn with the item equipped. Is there anything else I have to do for this?
  14. I figured it out. I'll post what I did in case anyone else is doing something similar to what I'm doing. My predicate code is the same with the exception that chunks are retrieved with serverLevelAccessor.getChunk instead of level.getChunkAt. My utility function for getting the blocks from a chunk is the following: public static Stream<Block> getBlocksFromChunk(ChunkAccess chunk) { if (chunk instanceof LevelChunk levelChunk) { List<Block> blocks = new ArrayList<>(); Arrays.stream(levelChunk.getSections()).forEach(section -> section.getStates().getAll(blockState -> blocks.add(blockState.getBlock()))); return blocks.stream(); } else { return Stream.empty(); } }
  15. The subscriber maybe, but the when I was debugging the predicate I was hitting the breakpoint after world gen.
×
×
  • Create New...

Important Information

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