Initial commit: Forge 1.20.1 Ellie companion mod

- EllieEntity with GeckoLib animations, sleep AI, pathfinding with crouching
- Dialog system with conditions and effects
- Relationship system with milestones
- OpenDoor and bed occupation pathfinding
- 15 animations: idle1/2/3, sleep, walkingsimple, shiftwalking/shiftidle, etc.
This commit is contained in:
2026-06-09 21:18:04 +03:00
commit f5d318f02e
48 changed files with 21932 additions and 0 deletions
@@ -0,0 +1,85 @@
package me.sashegdev.fabled_hearts;
import com.mojang.logging.LogUtils;
import me.sashegdev.fabled_hearts.dialog.DialogLoader;
import me.sashegdev.fabled_hearts.dialog.DialogManager;
import me.sashegdev.fabled_hearts.entity.ellie.EllieEntity;
import me.sashegdev.fabled_hearts.entity.ellie.EllieRenderer;
import me.sashegdev.fabled_hearts.network.ModNetworking;
import me.sashegdev.fabled_hearts.registry.ModEntities;
import me.sashegdev.fabled_hearts.registry.ModItems;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.AddReloadListenerEvent;
import net.minecraftforge.event.entity.EntityAttributeCreationEvent;
import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.slf4j.Logger;
import software.bernie.geckolib.GeckoLib;
@Mod(Main.MODID)
public class Main {
public static final String MODID = "fabled_hearts";
public static final Logger LOGGER = LogUtils.getLogger();
public Main() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
GeckoLib.initialize();
new DialogManager();
ModEntities.register(modEventBus);
ModItems.register(modEventBus);
modEventBus.addListener(this::commonSetup);
modEventBus.register(CommonHandler.class);
modEventBus.register(ClientHandler.class);
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(new ForgeHandler());
}
private void commonSetup(FMLCommonSetupEvent event) {
event.enqueueWork(ModNetworking::register);
}
@Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
public static class CommonHandler {
@SubscribeEvent
public static void registerAttributes(EntityAttributeCreationEvent event) {
event.put(ModEntities.ELLIE.get(), EllieEntity.createAttributes().build());
}
}
@Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public static class ClientHandler {
@SubscribeEvent
public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(ModEntities.ELLIE.get(), EllieRenderer::new);
}
}
public static class ForgeHandler {
@SubscribeEvent
public void onAddReloadListeners(AddReloadListenerEvent event) {
event.addListener(new DialogLoader());
}
@SubscribeEvent
public void onBlockBreak(BlockEvent.BreakEvent event) {
if (!event.getLevel().isClientSide()) {
var pos = event.getPos();
event.getLevel().getEntitiesOfClass(
EllieEntity.class,
new net.minecraft.world.phys.AABB(pos).inflate(2),
e -> e.isSleeping() && pos.equals(e.getBedPos())
).forEach(EllieEntity::wakeUp);
}
}
}
}