diff --git a/.tmp/software/bernie/geckolib/animatable/GeoBlockEntity.java b/.tmp/software/bernie/geckolib/animatable/GeoBlockEntity.java
new file mode 100644
index 00000000..170ed02c
--- /dev/null
+++ b/.tmp/software/bernie/geckolib/animatable/GeoBlockEntity.java
@@ -0,0 +1,146 @@
+package software.bernie.geckolib.animatable;
+
+import net.minecraft.class_1937;
+import net.minecraft.class_2586;
+import net.minecraft.class_3218;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+import software.bernie.geckolib.GeckoLibConstants;
+import software.bernie.geckolib.GeckoLibServices;
+import software.bernie.geckolib.animation.AnimatableManager;
+import software.bernie.geckolib.animation.AnimationController;
+import software.bernie.geckolib.constant.dataticket.SerializableDataTicket;
+import software.bernie.geckolib.util.RenderUtil;
+
+/**
+ * The {@link GeoAnimatable} interface specific to {@link class_2586 BlockEntities}
+ *
+ * @see GeckoLib Wiki - Block Animations
+ */
+public interface GeoBlockEntity extends GeoAnimatable {
+ /**
+ * Get server-synced animation data via its relevant {@link SerializableDataTicket}.
+ *
+ * Should only be used on the client-side
+ *
+ * DO NOT OVERRIDE
+ *
+ * @param dataTicket The data ticket for the data to retrieve
+ * @return The synced data, or null if no data of that type has been synced
+ */
+ @ApiStatus.NonExtendable
+ @Nullable
+ default D getAnimData(SerializableDataTicket dataTicket) {
+ return getAnimatableInstanceCache().getManagerForId(0).getData(dataTicket);
+ }
+
+ /**
+ * Saves an arbitrary piece of data to this animatable's {@link AnimatableManager}
+ *
+ * DO NOT OVERRIDE
+ *
+ * @param dataTicket The DataTicket to sync the data for
+ * @param data The data to sync
+ */
+ @ApiStatus.NonExtendable
+ default void setAnimData(SerializableDataTicket dataTicket, D data) {
+ class_2586 blockEntity = (class_2586)this;
+ class_1937 level = blockEntity.method_10997();
+
+ if (level == null) {
+ GeckoLibConstants.LOGGER.error("Attempting to set animation data for BlockEntity too early! Must wait until after the BlockEntity has been set in the world. (" + blockEntity.getClass().toString() + ")");
+
+ return;
+ }
+
+ if (level.method_8608()) {
+ getAnimatableInstanceCache().getManagerForId(0).setData(dataTicket, data);
+ }
+ else {
+ GeckoLibServices.NETWORK.syncBlockEntityAnimData(blockEntity.method_11016(), dataTicket, data, (class_3218)level);
+ }
+ }
+
+ /**
+ * Trigger an animation for this BlockEntity, based on the controller name and animation name
+ *
+ * This can be fired from either the client or the server, but optimally you would call it from the server
+ *
+ * DO NOT OVERRIDE
+ *
+ * @param controllerName The name of the controller name the animation belongs to, or null to do an inefficient lazy search
+ * @param animName The name of animation to trigger. This needs to have been registered with the controller via {@link AnimationController#triggerableAnim AnimationController.triggerableAnim}
+ */
+ @ApiStatus.NonExtendable
+ default void triggerAnim(@Nullable String controllerName, String animName) {
+ class_2586 blockEntity = (class_2586)this;
+ class_1937 level = blockEntity.method_10997();
+
+ if (level == null) {
+ GeckoLibConstants.LOGGER.error("Attempting to trigger an animation for a BlockEntity too early! Must wait until after the BlockEntity has been set in the world. (" + blockEntity.getClass().toString() + ")");
+
+ return;
+ }
+
+ if (level.method_8608()) {
+ if (controllerName != null) {
+ getAnimatableInstanceCache().getManagerForId(0).tryTriggerAnimation(controllerName, animName);
+ }
+ else {
+ getAnimatableInstanceCache().getManagerForId(0).tryTriggerAnimation(animName);
+ }
+ }
+ else {
+ GeckoLibServices.NETWORK.triggerBlockEntityAnim(blockEntity.method_11016(), controllerName, animName, (class_3218)level);
+ }
+ }
+
+ /**
+ * Stop a previously triggered animation for this BlockEntity for the given controller name and animation name
+ *
+ * This can be fired from either the client or the server, but optimally you would call it from the server
+ *
+ * DO NOT OVERRIDE
+ *
+ * @param controllerName The name of the controller name the animation belongs to, or null to do an inefficient lazy search
+ * @param animName The name of the triggered animation to stop, or null to stop any currently playing triggered animation
+ */
+ @ApiStatus.NonExtendable
+ default void stopTriggeredAnim(@Nullable String controllerName, @Nullable String animName) {
+ class_2586 blockEntity = (class_2586)this;
+ class_1937 level = blockEntity.method_10997();
+
+ if (level == null) {
+ GeckoLibConstants.LOGGER.error("Attempting to stop a triggered animation for a BlockEntity too early! Must wait until after the BlockEntity has been set in the world. (" + blockEntity.getClass().toString() + ")");
+
+ return;
+ }
+
+ if (level.method_8608()) {
+ AnimatableManager animatableManager = getAnimatableInstanceCache().getManagerForId(0);
+
+ if (controllerName != null) {
+ animatableManager.stopTriggeredAnimation(controllerName, animName);
+ }
+ else {
+ animatableManager.stopTriggeredAnimation(animName);
+ }
+ }
+ else {
+ GeckoLibServices.NETWORK.stopTriggeredBlockEntityAnim(blockEntity.method_11016(), (class_3218)level, controllerName, animName);
+ }
+ }
+
+ /**
+ * Returns the current age/tick of the animatable instance
+ *
+ * By default this is just the animatable's age in ticks, but this method allows for non-ticking custom animatables to provide their own values
+ *
+ * @param blockEntity The BlockEntity representing this animatable
+ * @return The current tick/age of the animatable, for animation purposes
+ */
+ @Override
+ default double getTick(Object blockEntity) {
+ return RenderUtil.getCurrentTick();
+ }
+}
diff --git a/.tmp/software/bernie/geckolib/model/DefaultedBlockGeoModel.java b/.tmp/software/bernie/geckolib/model/DefaultedBlockGeoModel.java
new file mode 100644
index 00000000..799e55a8
--- /dev/null
+++ b/.tmp/software/bernie/geckolib/model/DefaultedBlockGeoModel.java
@@ -0,0 +1,65 @@
+package software.bernie.geckolib.model;
+
+import net.minecraft.class_2960;
+import software.bernie.geckolib.animatable.GeoAnimatable;
+
+/**
+ * {@link DefaultedGeoModel} specific to {@link net.minecraft.class_2248 Blocks}
+ *
+ * Using this class pre-sorts provided asset paths into the "block" subdirectory
+ */
+public class DefaultedBlockGeoModel extends DefaultedGeoModel {
+ /**
+ * Create a new instance of this model class
+ *
+ * The asset path should be the truncated relative path from the base folder
+ *
+ * E.G.
+ *
{@code
+ * new ResourceLocation("myMod", "workbench/sawmill")
+ * }
+ */
+ public DefaultedBlockGeoModel(class_2960 assetSubpath) {
+ super(assetSubpath);
+ }
+
+ /**
+ * Returns the subtype string for this type of model
+ *
+ * This allows for sorting of asset files into neat subdirectories for clean management.
+ */
+ @Override
+ protected String subtype() {
+ return "block";
+ }
+
+ /**
+ * Changes the constructor-defined model path for this model to an alternate
+ *
+ * This is useful if your animatable shares a model path with another animatable that differs in path to the texture and animations for this model
+ */
+ @Override
+ public DefaultedBlockGeoModel withAltModel(class_2960 altPath) {
+ return (DefaultedBlockGeoModel)super.withAltModel(altPath);
+ }
+
+ /**
+ * Changes the constructor-defined animations path for this model to an alternate
+ *
+ * This is useful if your animatable shares an animations path with another animatable that differs in path to the model and texture for this model
+ */
+ @Override
+ public DefaultedBlockGeoModel withAltAnimations(class_2960 altPath) {
+ return (DefaultedBlockGeoModel)super.withAltAnimations(altPath);
+ }
+
+ /**
+ * Changes the constructor-defined texture path for this model to an alternate
+ *
+ * This is useful if your animatable shares a texture path with another animatable that differs in path to the model and animations for this model
+ */
+ @Override
+ public DefaultedBlockGeoModel withAltTexture(class_2960 altPath) {
+ return (DefaultedBlockGeoModel)super.withAltTexture(altPath);
+ }
+}
diff --git a/.tmp/software/bernie/geckolib/model/GeoModel.java b/.tmp/software/bernie/geckolib/model/GeoModel.java
new file mode 100644
index 00000000..3e17328b
--- /dev/null
+++ b/.tmp/software/bernie/geckolib/model/GeoModel.java
@@ -0,0 +1,250 @@
+package software.bernie.geckolib.model;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+import software.bernie.geckolib.GeckoLibConstants;
+import software.bernie.geckolib.animatable.GeoAnimatable;
+import software.bernie.geckolib.animatable.GeoReplacedEntity;
+import software.bernie.geckolib.animation.AnimatableManager;
+import software.bernie.geckolib.animation.Animation;
+import software.bernie.geckolib.animation.AnimationProcessor;
+import software.bernie.geckolib.animation.AnimationState;
+import software.bernie.geckolib.cache.GeckoLibCache;
+import software.bernie.geckolib.cache.object.BakedGeoModel;
+import software.bernie.geckolib.cache.object.GeoBone;
+import software.bernie.geckolib.constant.DataTickets;
+import software.bernie.geckolib.constant.dataticket.DataTicket;
+import software.bernie.geckolib.loading.object.BakedAnimations;
+import software.bernie.geckolib.renderer.GeoRenderer;
+import software.bernie.geckolib.util.RenderUtil;
+
+import java.util.Optional;
+import java.util.function.BiConsumer;
+import java.util.function.DoubleSupplier;
+import net.minecraft.class_1297;
+import net.minecraft.class_1921;
+import net.minecraft.class_2960;
+import net.minecraft.class_310;
+
+/**
+ * Base class for all code-based model objects
+ *
+ * All models registered to a {@link GeoRenderer} must be an instance of this or one of its subclasses
+ *
+ * @see GeckoLib Wiki - Models
+ */
+public abstract class GeoModel {
+ private final AnimationProcessor processor = new AnimationProcessor<>(this);
+
+ private BakedGeoModel currentModel = null;
+ private double animTime;
+ private double lastGameTickTime;
+ private long lastRenderedInstance = -1;
+
+ /**
+ * Returns the resource path for the {@link BakedGeoModel} (model json file) to render based on the provided animatable
+ */
+ public class_2960 getModelResource(T animatable, @Nullable GeoRenderer renderer) {
+ return getModelResource(animatable);
+ }
+
+ /**
+ * Returns the resource path for the {@link BakedGeoModel} (model json file) to render based on the provided animatable
+ */
+ @Deprecated
+ public abstract class_2960 getModelResource(T animatable);
+
+ /**
+ * Returns the resource path for the texture file to render based on the provided animatable
+ */
+ public class_2960 getTextureResource(T animatable, @Nullable GeoRenderer renderer) {
+ return getTextureResource(animatable);
+ }
+
+ /**
+ * Returns the resource path for the texture file to render based on the provided animatable
+ */
+ @Deprecated
+ public abstract class_2960 getTextureResource(T animatable);
+
+ /**
+ * Returns the resource path for the {@link BakedAnimations} (animation json file) to use for animations based on the provided animatable
+ */
+ public abstract class_2960 getAnimationResource(T animatable);
+
+ /**
+ * Returns the resource path for the {@link BakedAnimations} (animation json file) fallback locations in the event
+ * your animation isn't present in the {@link #getAnimationResource(GeoAnimatable) primary resource}.
+ *
+ * Should NOT be used as the primary animation resource path, and in general shouldn't be used
+ * at all unless you know what you are doing
+ */
+ public class_2960[] getAnimationResourceFallbacks(T animatable) {
+ return new class_2960[0];
+ }
+
+ /**
+ * Override this and return true if Geckolib should crash when attempting to animate the model, but fails to find a bone
+ *
+ * By default, GeckoLib will just gracefully ignore a missing bone, which might cause oddities with incorrect models or mismatching variables
+ */
+ public boolean crashIfBoneMissing() {
+ return false;
+ }
+
+ /**
+ * Gets the default render type for this animatable, to be selected by default by the renderer using it
+ *
+ * @return Return the RenderType to use, or null to prevent the model rendering. Returning null will not prevent animation functions taking place
+ */
+ @Nullable
+ public class_1921 getRenderType(T animatable, class_2960 texture) {
+ return class_1921.method_23578(texture);
+ }
+
+ /**
+ * Get the baked geo model object used for rendering from the given resource path
+ */
+ public BakedGeoModel getBakedModel(class_2960 location) {
+ BakedGeoModel model = GeckoLibCache.getBakedModels().get(location);
+
+ if (model == null) {
+ if (!location.method_12832().contains("geo/"))
+ throw GeckoLibConstants.exception(location, "Invalid model resource path provided - GeckoLib models must be placed in assets//geo/");
+
+ throw GeckoLibConstants.exception(location, "Unable to find model");
+ }
+
+ if (model != this.currentModel) {
+ this.processor.setActiveModel(model);
+ this.currentModel = model;
+ }
+
+ return this.currentModel;
+ }
+
+ /**
+ * Gets a bone from this model by name
+ *
+ * @param name The name of the bone
+ * @return An {@link Optional} containing the {@link software.bernie.geckolib.cache.object.GeoBone} if one matches, otherwise an empty Optional
+ */
+ public Optional getBone(String name) {
+ return Optional.ofNullable(getAnimationProcessor().getBone(name));
+ }
+
+ /**
+ * Gets the loaded {@link Animation} for the given animation {@code name}, if it exists
+ *
+ * @param animatable The {@code GeoAnimatable} instance being referred to
+ * @param name The name of the animation to retrieve
+ * @return The {@code Animation} instance for the provided {@code name}, or null if none match
+ */
+ @Nullable
+ public Animation getAnimation(T animatable, String name) {
+ class_2960 location = getAnimationResource(animatable);
+ BakedAnimations bakedAnimations = GeckoLibCache.getBakedAnimations().get(location);
+ Animation animation = bakedAnimations != null ? bakedAnimations.getAnimation(name) : null;
+
+ if (animation != null)
+ return animation;
+
+ for (class_2960 fallbackLocation : getAnimationResourceFallbacks(animatable)) {
+ bakedAnimations = GeckoLibCache.getBakedAnimations().get(location = fallbackLocation);
+ animation = bakedAnimations != null ? bakedAnimations.getAnimation(name) : null;
+
+ if (animation != null)
+ return animation;
+ }
+
+ if (bakedAnimations == null) {
+ if (!location.method_12832().contains("animations/"))
+ throw GeckoLibConstants.exception(location, "Invalid animation resource path provided - GeckoLib animations must be placed in assets//animations/");
+
+ throw GeckoLibConstants.exception(location, "Unable to find animation file.");
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the {@link AnimationProcessor} for this model.
+ */
+ public AnimationProcessor getAnimationProcessor() {
+ return this.processor;
+ }
+
+ /**
+ * Add additional {@link DataTicket DataTickets} to the {@link AnimationState} to be handled by your animation handler at render time
+ *
+ * @param animatable The animatable instance currently being animated
+ * @param instanceId The unique instance id of the animatable being animated
+ * @param dataConsumer The DataTicket + data consumer to be added to the AnimationEvent
+ */
+ public void addAdditionalStateData(T animatable, long instanceId, BiConsumer, T> dataConsumer) {}
+
+ /**
+ * This method is called once per render-frame for each {@link GeoAnimatable} being rendered
+ *
+ * It is an internal method for automated animation parsing. Use {@link GeoModel#setCustomAnimations(GeoAnimatable, long, AnimationState)} for custom animation work
+ */
+ @ApiStatus.Internal
+ public void handleAnimations(T animatable, long instanceId, AnimationState animationState, float partialTick) {
+ class_310 mc = class_310.method_1551();
+ AnimatableManager animatableManager = animatable.getAnimatableInstanceCache().getManagerForId(instanceId);
+ Double currentTick = animationState.getData(DataTickets.TICK);
+
+ if (currentTick == null)
+ currentTick = animatable instanceof class_1297 entity ? (double)entity.field_6012 : RenderUtil.getCurrentTick();
+
+ if (animatableManager.getFirstTickTime() == -1)
+ animatableManager.startedAt(currentTick + partialTick);
+
+ double currentFrameTime = animatable instanceof class_1297 || animatable instanceof GeoReplacedEntity ? currentTick + partialTick : currentTick - animatableManager.getFirstTickTime();
+ boolean isReRender = !animatableManager.isFirstTick() && currentFrameTime == animatableManager.getLastUpdateTime();
+
+ if (isReRender && instanceId == this.lastRenderedInstance)
+ return;
+
+ if (!mc.method_1493() || animatable.shouldPlayAnimsWhileGamePaused()) {
+ animatableManager.updatedAt(currentFrameTime);
+
+ double lastUpdateTime = animatableManager.getLastUpdateTime();
+ this.animTime += lastUpdateTime - this.lastGameTickTime;
+ this.lastGameTickTime = lastUpdateTime;
+ }
+
+ animationState.animationTick = this.animTime;
+ this.lastRenderedInstance = instanceId;
+ AnimationProcessor processor = getAnimationProcessor();
+
+ processor.preAnimationSetup(animationState, this.animTime);
+
+ if (!processor.getRegisteredBones().isEmpty())
+ processor.tickAnimation(animatable, this, animatableManager, this.animTime, animationState, crashIfBoneMissing());
+
+ setCustomAnimations(animatable, instanceId, animationState);
+ }
+
+ /**
+ * This method is called once per render-frame for each {@link GeoAnimatable} being rendered
+ *
+ * Override to set custom animations (such as head rotation, etc)
+ *
+ * @param animatable The {@code GeoAnimatable} instance currently being rendered
+ * @param instanceId The instance id of the {@code GeoAnimatable}
+ * @param animationState An {@link AnimationState} instance created to hold animation data for the {@code animatable} for this method call
+ */
+ public void setCustomAnimations(T animatable, long instanceId, AnimationState animationState) {}
+
+ /**
+ * This method is called once per render-frame for each {@link GeoAnimatable} being rendered
+ *
+ * Use this method to set custom {@link software.bernie.geckolib.loading.math.value.Variable Variable} values via
+ * {@link software.bernie.geckolib.loading.math.MathParser#setVariable(String, DoubleSupplier) MathParser.setVariable}
+ *
+ * @param animationState The AnimationState data for the current render frame
+ * @param animTime The internal tick counter kept by the {@link AnimatableManager manager} for this animatable
+ */
+ public void applyMolangQueries(AnimationState animationState, double animTime) {}
+}
diff --git a/.tmp/software/bernie/geckolib/renderer/GeoBlockRenderer.java b/.tmp/software/bernie/geckolib/renderer/GeoBlockRenderer.java
new file mode 100644
index 00000000..2f8bfa7d
--- /dev/null
+++ b/.tmp/software/bernie/geckolib/renderer/GeoBlockRenderer.java
@@ -0,0 +1,272 @@
+package software.bernie.geckolib.renderer;
+
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Matrix4f;
+import org.joml.Vector3f;
+import software.bernie.geckolib.GeckoLibServices;
+import software.bernie.geckolib.animatable.GeoAnimatable;
+import software.bernie.geckolib.animation.AnimationState;
+import software.bernie.geckolib.cache.object.BakedGeoModel;
+import software.bernie.geckolib.cache.object.GeoBone;
+import software.bernie.geckolib.cache.texture.AnimatableTexture;
+import software.bernie.geckolib.constant.DataTickets;
+import software.bernie.geckolib.model.DefaultedBlockGeoModel;
+import software.bernie.geckolib.model.GeoModel;
+import software.bernie.geckolib.renderer.layer.GeoRenderLayer;
+import software.bernie.geckolib.renderer.layer.GeoRenderLayersContainer;
+import software.bernie.geckolib.util.RenderUtil;
+
+import java.util.List;
+import net.minecraft.class_1921;
+import net.minecraft.class_2318;
+import net.minecraft.class_2338;
+import net.minecraft.class_2350;
+import net.minecraft.class_2383;
+import net.minecraft.class_2586;
+import net.minecraft.class_2591;
+import net.minecraft.class_2680;
+import net.minecraft.class_4587;
+import net.minecraft.class_4588;
+import net.minecraft.class_4597;
+import net.minecraft.class_7833;
+import net.minecraft.class_7923;
+import net.minecraft.class_827;
+
+/**
+ * Base {@link GeoRenderer} class for rendering {@link class_2586 Blocks} specifically
+ *
+ * All blocks added to be rendered by GeckoLib should use an instance of this class.
+ */
+public class GeoBlockRenderer implements GeoRenderer, class_827 {
+ protected final GeoRenderLayersContainer renderLayers = new GeoRenderLayersContainer<>(this);
+ protected final GeoModel model;
+
+ protected T animatable;
+ protected float scaleWidth = 1;
+ protected float scaleHeight = 1;
+
+ protected Matrix4f blockRenderTranslations = new Matrix4f();
+ protected Matrix4f modelRenderTranslations = new Matrix4f();
+
+ /**
+ * Creates a new defaulted renderer instance, using the blockentity's registered id as the file name for its assets
+ */
+ public GeoBlockRenderer(class_2591 extends T> blockEntityType) {
+ this(new DefaultedBlockGeoModel<>(class_7923.field_41181.method_10221(blockEntityType)));
+ }
+
+ public GeoBlockRenderer(GeoModel model) {
+ this.model = model;
+ }
+
+ /**
+ * Gets the model instance for this renderer
+ */
+ @Override
+ public GeoModel getGeoModel() {
+ return this.model;
+ }
+
+ /**
+ * Gets the {@link GeoAnimatable} instance currently being rendered
+ */
+ @Override
+ public T getAnimatable() {
+ return this.animatable;
+ }
+
+ /**
+ * Gets the id that represents the current animatable's instance for animation purposes
+ *
+ * This is mostly useful for things like items, which have a single registered instance for all objects
+ */
+ @Override
+ public long getInstanceId(T animatable) {
+ return animatable.method_11016().hashCode();
+ }
+
+ /**
+ * Returns the list of registered {@link GeoRenderLayer GeoRenderLayers} for this renderer
+ */
+ @Override
+ public List> getRenderLayers() {
+ return this.renderLayers.getRenderLayers();
+ }
+
+ /**
+ * Adds a {@link GeoRenderLayer} to this renderer, to be called after the main model is rendered each frame
+ */
+ public GeoBlockRenderer addRenderLayer(GeoRenderLayer renderLayer) {
+ this.renderLayers.addLayer(renderLayer);
+
+ return this;
+ }
+
+ /**
+ * Sets a scale override for this renderer, telling GeckoLib to pre-scale the model
+ */
+ public GeoBlockRenderer withScale(float scale) {
+ return withScale(scale, scale);
+ }
+
+ /**
+ * Sets a scale override for this renderer, telling GeckoLib to pre-scale the model
+ */
+ public GeoBlockRenderer withScale(float scaleWidth, float scaleHeight) {
+ this.scaleWidth = scaleWidth;
+ this.scaleHeight = scaleHeight;
+
+ return this;
+ }
+
+ /**
+ * Called before rendering the model to buffer. Allows for render modifications and preparatory work such as scaling and translating
+ *
+ * {@link class_4587} translations made here are kept until the end of the render process
+ */
+ @Override
+ public void preRender(class_4587 poseStack, T animatable, BakedGeoModel model, @Nullable class_4597 bufferSource, @Nullable class_4588 buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, int colour) {
+ this.blockRenderTranslations = new Matrix4f(poseStack.method_23760().method_23761());
+
+ if (!isReRender)
+ poseStack.method_22904(0.5, 0, 0.5);
+
+ scaleModelForRender(this.scaleWidth, this.scaleHeight, poseStack, animatable, model, isReRender, partialTick, packedLight, packedOverlay);
+ }
+
+ @Override
+ @ApiStatus.Internal
+ public void method_3569(T animatable, float partialTick, class_4587 poseStack, class_4597 bufferSource,
+ int packedLight, int packedOverlay) {
+ this.animatable = animatable;
+
+ defaultRender(poseStack, this.animatable, bufferSource, null, null, 0, partialTick, packedLight);
+ }
+
+ /**
+ * The actual render method that subtype renderers should override to handle their specific rendering tasks
+ *
+ * {@link GeoRenderer#preRender} has already been called by this stage, and {@link GeoRenderer#postRender} will be called directly after
+ */
+ @Override
+ public void actuallyRender(class_4587 poseStack, T animatable, BakedGeoModel model, @Nullable class_1921 renderType,
+ class_4597 bufferSource, @Nullable class_4588 buffer, boolean isReRender, float partialTick, int packedLight,
+ int packedOverlay, int colour) {
+ if (!isReRender) {
+ AnimationState animationState = new AnimationState(animatable, 0, 0, partialTick, false);
+ long instanceId = getInstanceId(animatable);
+ GeoModel currentModel = getGeoModel();
+
+ animationState.setData(DataTickets.TICK, animatable.getTick(animatable));
+ animationState.setData(DataTickets.BLOCK_ENTITY, animatable);
+ currentModel.addAdditionalStateData(animatable, instanceId, animationState::setData);
+ rotateBlock(getFacing(animatable), poseStack);
+ currentModel.handleAnimations(animatable, instanceId, animationState, partialTick);
+ }
+
+ this.modelRenderTranslations = new Matrix4f(poseStack.method_23760().method_23761());
+
+ if (buffer != null)
+ GeoRenderer.super.actuallyRender(poseStack, animatable, model, renderType, bufferSource, buffer, isReRender, partialTick,
+ packedLight, packedOverlay, colour);
+ }
+
+ /**
+ * Called after all render operations are completed and the render pass is considered functionally complete.
+ *
+ * Use this method to clean up any leftover persistent objects stored during rendering or any other post-render maintenance tasks as required
+ */
+ @Override
+ public void doPostRenderCleanup() {
+ this.animatable = null;
+ }
+
+ /**
+ * Renders the provided {@link GeoBone} and its associated child bones
+ */
+ @Override
+ public void renderRecursively(class_4587 poseStack, T animatable, GeoBone bone, class_1921 renderType, class_4597 bufferSource, class_4588 buffer, boolean isReRender, float partialTick, int packedLight,
+ int packedOverlay, int colour) {
+ if (bone.isTrackingMatrices()) {
+ Matrix4f poseState = new Matrix4f(poseStack.method_23760().method_23761());
+ Matrix4f localMatrix = RenderUtil.invertAndMultiplyMatrices(poseState, this.blockRenderTranslations);
+ Matrix4f worldState = new Matrix4f(localMatrix);
+ class_2338 pos = this.animatable.method_11016();
+
+ bone.setModelSpaceMatrix(RenderUtil.invertAndMultiplyMatrices(poseState, this.modelRenderTranslations));
+ bone.setLocalSpaceMatrix(localMatrix);
+ bone.setWorldSpaceMatrix(worldState.translate(new Vector3f(pos.method_10263(), pos.method_10264(), pos.method_10260())));
+ }
+
+ GeoRenderer.super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay,
+ colour);
+ }
+
+ /**
+ * Rotate the {@link class_4587} based on the determined {@link class_2350} the block is facing
+ */
+ protected void rotateBlock(class_2350 facing, class_4587 poseStack) {
+ switch (facing) {
+ case field_11035 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(180));
+ case field_11039 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(90));
+ case field_11043 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(0));
+ case field_11034 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(270));
+ case field_11036 -> poseStack.method_22907(class_7833.field_40714.rotationDegrees(90));
+ case field_11033 -> poseStack.method_22907(class_7833.field_40713.rotationDegrees(90));
+ }
+ }
+
+ /**
+ * Attempt to extract a direction from the block so that the model can be oriented correctly
+ */
+ protected class_2350 getFacing(T block) {
+ class_2680 blockState = block.method_11010();
+
+ if (blockState.method_28498(class_2383.field_11177))
+ return blockState.method_11654(class_2383.field_11177);
+
+ if (blockState.method_28498(class_2318.field_10927))
+ return blockState.method_11654(class_2318.field_10927);
+
+ return class_2350.field_11043;
+ }
+
+ /**
+ * Update the current frame of a {@link AnimatableTexture potentially animated} texture used by this GeoRenderer
+ *
+ * This should only be called immediately prior to rendering
+ *
+ * @see AnimatableTexture#setAndUpdate
+ */
+ @Override
+ public void updateAnimatedTextureFrame(T animatable) {
+ AnimatableTexture.setAndUpdate(getTextureLocation(animatable));
+ }
+
+ /**
+ * Create and fire the relevant {@code CompileLayers} event hook for this renderer
+ */
+ @Override
+ public void fireCompileRenderLayersEvent() {
+ GeckoLibServices.Client.EVENTS.fireCompileBlockRenderLayers(this);
+ }
+
+ /**
+ * Create and fire the relevant {@code Pre-Render} event hook for this renderer
+ *
+ * @return Whether the renderer should proceed based on the cancellation state of the event
+ */
+ @Override
+ public boolean firePreRenderEvent(class_4587 poseStack, BakedGeoModel model, class_4597 bufferSource, float partialTick, int packedLight) {
+ return GeckoLibServices.Client.EVENTS.fireBlockPreRender(this, poseStack, model, bufferSource, partialTick, packedLight);
+ }
+
+ /**
+ * Create and fire the relevant {@code Post-Render} event hook for this renderer
+ */
+ @Override
+ public void firePostRenderEvent(class_4587 poseStack, BakedGeoModel model, class_4597 bufferSource, float partialTick, int packedLight) {
+ GeckoLibServices.Client.EVENTS.fireBlockPostRender(this, poseStack, model, bufferSource, partialTick, packedLight);
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/AntarchyObjects.java b/common/src/main/java/com/craisinlord/antarchy/content/AntarchyObjects.java
index 9b3adf8b..27092e51 100644
--- a/common/src/main/java/com/craisinlord/antarchy/content/AntarchyObjects.java
+++ b/common/src/main/java/com/craisinlord/antarchy/content/AntarchyObjects.java
@@ -29,6 +29,7 @@ import com.craisinlord.antarchy.content.entity.ReverieEntity;
import com.craisinlord.antarchy.content.entity.ScorpionEntity;
import com.craisinlord.antarchy.content.block.entity.AntNestBlockEntity;
import com.craisinlord.antarchy.content.block.entity.DreamCampfireBlockEntity;
+import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
import com.craisinlord.antarchy.content.block.entity.WaspNestBlockEntity;
import java.util.function.Supplier;
import net.minecraft.core.Holder;
@@ -292,6 +293,10 @@ public final class AntarchyObjects {
@SuppressWarnings("unchecked")
public static Supplier GIANT_LILY_PAD = (Supplier) UNBOUND;
@SuppressWarnings("unchecked")
+ public static Supplier LOTUS = (Supplier) UNBOUND;
+ @SuppressWarnings("unchecked")
+ public static Supplier SEASHELL = (Supplier) UNBOUND;
+ @SuppressWarnings("unchecked")
public static Supplier> ANT_NEST_BLOCK_ENTITY = (Supplier>) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier> DREAM_CAMPFIRE_BLOCK_ENTITY = (Supplier>) UNBOUND;
@@ -300,6 +305,8 @@ public final class AntarchyObjects {
@SuppressWarnings("unchecked")
public static Supplier> HUSHWEED_BLOCK_ENTITY = (Supplier>) UNBOUND;
@SuppressWarnings("unchecked")
+ public static Supplier> SEASHELL_BLOCK_ENTITY = (Supplier>) UNBOUND;
+ @SuppressWarnings("unchecked")
public static Supplier STINKY_GAS = (Supplier) UNBOUND;
@SuppressWarnings("unchecked")
public static Supplier STINKY_FLY = (Supplier) UNBOUND;
@@ -401,10 +408,12 @@ public final class AntarchyObjects {
Supplier squirrelNestBlock,
Supplier brutalflyCocoonSpawner,
Supplier giantLilyPad,
+ Supplier seashell,
Supplier> antNestBlockEntity,
Supplier> dreamCampfireBlockEntity,
Supplier> waspNestBlockEntity,
Supplier> hushweedBlockEntity,
+ Supplier> seashellBlockEntity,
Supplier stinkyGas,
Supplier stinkyFly,
Supplier peachLeaves,
@@ -500,10 +509,12 @@ public final class AntarchyObjects {
SQUIRREL_NEST_BLOCK = squirrelNestBlock;
BRUTALFLY_COCOON_SPAWNER = brutalflyCocoonSpawner;
GIANT_LILY_PAD = giantLilyPad;
+ SEASHELL = seashell;
ANT_NEST_BLOCK_ENTITY = antNestBlockEntity;
DREAM_CAMPFIRE_BLOCK_ENTITY = dreamCampfireBlockEntity;
WASP_NEST_BLOCK_ENTITY = waspNestBlockEntity;
HUSHWEED_BLOCK_ENTITY = hushweedBlockEntity;
+ SEASHELL_BLOCK_ENTITY = seashellBlockEntity;
STINKY_GAS = stinkyGas;
STINKY_FLY = stinkyFly;
PEACH_LEAVES_PARTICLE = peachLeaves;
@@ -524,6 +535,10 @@ public final class AntarchyObjects {
TENTACLE = supplier;
}
+ public static void setLotus(Supplier supplier) {
+ LOTUS = supplier;
+ }
+
public static void setKrakensGraspTrident(Supplier> supplier) {
KRAKENS_GRASP_TRIDENT = supplier;
}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/CreativeTabOrder.java b/common/src/main/java/com/craisinlord/antarchy/content/CreativeTabOrder.java
index 8ce4587f..60b97f39 100644
--- a/common/src/main/java/com/craisinlord/antarchy/content/CreativeTabOrder.java
+++ b/common/src/main/java/com/craisinlord/antarchy/content/CreativeTabOrder.java
@@ -59,7 +59,7 @@ public final class CreativeTabOrder {
"myrmite", "broodstone", "chiten_block", "chiten_spike", "amber_moss_block", "amber_moss_carpet" -> 8;
case "ouranwood_leaves", "peach_leaves" -> 9;
case "duplicator_sapling", "ouranwood_acorn", "peach_sapling", "corn_seeds" -> 10;
- case "orange_milkweed", "pink_milkweed", "camellia", "spider_lily", "hushweed", "amber_lichen", "creepvine",
+ case "orange_milkweed", "pink_milkweed", "camellia", "spider_lily", "lotus", "hushweed", "amber_lichen", "creepvine",
"triffid_goo_block", "cloud_block", "wasp_nest",
"red_ant_nest", "brown_ant_nest", "rainbow_ant_nest", "termite_nest",
"star_coral", "star_coral_fan", "star_coral_block",
@@ -179,6 +179,7 @@ public final class CreativeTabOrder {
case "dead_star_coral" -> 17;
case "dead_star_coral_fan" -> 18;
case "dead_star_coral_block" -> 19;
+ case "lotus" -> 20;
case "blood_crystal_block" -> 0;
case "small_blood_crystal_bud" -> 1;
case "medium_blood_crystal_bud" -> 2;
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/block/GiantLilyPadBlock.java b/common/src/main/java/com/craisinlord/antarchy/content/block/GiantLilyPadBlock.java
index be01b968..a3986713 100644
--- a/common/src/main/java/com/craisinlord/antarchy/content/block/GiantLilyPadBlock.java
+++ b/common/src/main/java/com/craisinlord/antarchy/content/block/GiantLilyPadBlock.java
@@ -1,5 +1,6 @@
package com.craisinlord.antarchy.content.block;
+import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchyTags;
import com.mojang.serialization.MapCodec;
import java.util.ArrayList;
@@ -8,6 +9,7 @@ import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
+import net.minecraft.util.RandomSource;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
@@ -15,6 +17,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockBehaviour;
@@ -25,7 +28,7 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
-public final class GiantLilyPadBlock extends Block {
+public final class GiantLilyPadBlock extends Block implements BonemealableBlock {
public static final MapCodec CODEC = Block.simpleCodec(GiantLilyPadBlock::new);
public static final EnumProperty SHAPE = EnumProperty.create("shape", Shape.class);
public static final EnumProperty TILE_POSITION = EnumProperty.create("tile_position", TilePosition.class);
@@ -73,6 +76,68 @@ public final class GiantLilyPadBlock extends Block {
return isSupported(level, pos);
}
+ @Override
+ public boolean isValidBonemealTarget(LevelReader level, BlockPos pos, BlockState state) {
+ if (isThreeByThreeCenter(state)) {
+ return level.isEmptyBlock(pos.above());
+ }
+
+ return state.getValue(SHAPE) != Shape.THREE_BY_THREE;
+ }
+
+ @Override
+ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) {
+ return true;
+ }
+
+ @Override
+ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) {
+ if (isThreeByThreeCenter(state)) {
+ growLotus(level, pos);
+ return;
+ }
+
+ if (state.getValue(SHAPE) == Shape.THREE_BY_THREE) {
+ return;
+ }
+
+ spreadNearby(level, random, pos);
+ }
+
+ private static boolean isThreeByThreeCenter(BlockState state) {
+ return state.getValue(SHAPE) == Shape.THREE_BY_THREE && state.getValue(TILE_POSITION) == TilePosition.CENTER;
+ }
+
+ private static void growLotus(ServerLevel level, BlockPos padPos) {
+ BlockPos abovePos = padPos.above();
+ if (!level.isEmptyBlock(abovePos)) {
+ return;
+ }
+
+ BlockState lotusState = AntarchyObjects.LOTUS.get().defaultBlockState();
+ if (lotusState.canSurvive(level, abovePos)) {
+ level.setBlock(abovePos, lotusState, Block.UPDATE_ALL);
+ }
+ }
+
+ private static void spreadNearby(ServerLevel level, RandomSource random, BlockPos origin) {
+ for (int attempt = 0; attempt < 6; attempt++) {
+ int dx = random.nextInt(5) - 2;
+ int dz = random.nextInt(5) - 2;
+ if (dx == 0 && dz == 0) {
+ continue;
+ }
+
+ BlockPos candidate = origin.offset(dx, 0, dz);
+ if (!level.isEmptyBlock(candidate) || !isSupported(level, candidate)) {
+ continue;
+ }
+
+ level.setBlock(candidate, AntarchyObjects.GIANT_LILY_PAD.get().defaultBlockState(), Block.UPDATE_ALL);
+ return;
+ }
+ }
+
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (!state.canSurvive(level, pos)) {
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/block/LotusBlock.java b/common/src/main/java/com/craisinlord/antarchy/content/block/LotusBlock.java
new file mode 100644
index 00000000..b2e2ce3e
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/block/LotusBlock.java
@@ -0,0 +1,107 @@
+package com.craisinlord.antarchy.content.block;
+
+import com.mojang.serialization.MapCodec;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
+import net.minecraft.core.particles.DustParticleOptions;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.LevelAccessor;
+import net.minecraft.world.level.LevelReader;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.RenderShape;
+import net.minecraft.world.level.block.state.BlockBehaviour;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.block.state.StateDefinition;
+import net.minecraft.world.level.block.state.properties.BlockStateProperties;
+import net.minecraft.world.level.block.state.properties.BooleanProperty;
+import net.minecraft.world.phys.shapes.CollisionContext;
+import net.minecraft.world.phys.shapes.VoxelShape;
+import org.joml.Vector3f;
+
+public class LotusBlock extends Block {
+ public static final MapCodec CODEC = simpleCodec(LotusBlock::new);
+ public static final BooleanProperty HANGING = BlockStateProperties.HANGING;
+ private static final VoxelShape SHAPE = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 13.0D, 13.0D);
+ private static final Vector3f POLLEN_COLOR = new Vector3f(1.0F, 0.85F, 0.2F);
+
+ public LotusBlock(BlockBehaviour.Properties properties) {
+ super(properties);
+ this.registerDefaultState(this.stateDefinition.any().setValue(HANGING, false));
+ }
+
+ @Override
+ public MapCodec codec() {
+ return CODEC;
+ }
+
+ @Override
+ protected void createBlockStateDefinition(StateDefinition.Builder builder) {
+ builder.add(HANGING);
+ }
+
+ @Override
+ public BlockState getStateForPlacement(BlockPlaceContext context) {
+ Level level = context.getLevel();
+ BlockPos pos = context.getClickedPos();
+ boolean canHang = canSurvive(this.defaultBlockState().setValue(HANGING, true), level, pos);
+ boolean canStand = canSurvive(this.defaultBlockState().setValue(HANGING, false), level, pos);
+
+ if (context.getClickedFace() == Direction.DOWN && canHang) {
+ return this.defaultBlockState().setValue(HANGING, true);
+ }
+
+ if (canStand) {
+ return this.defaultBlockState().setValue(HANGING, false);
+ }
+
+ return canHang ? this.defaultBlockState().setValue(HANGING, true) : null;
+ }
+
+ @Override
+ protected RenderShape getRenderShape(BlockState state) {
+ return RenderShape.MODEL;
+ }
+
+ @Override
+ protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
+ return SHAPE;
+ }
+
+ @Override
+ protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
+ if (state.getValue(HANGING)) {
+ BlockPos abovePos = pos.above();
+ return level.getBlockState(abovePos).isFaceSturdy(level, abovePos, Direction.DOWN);
+ }
+
+ BlockPos belowPos = pos.below();
+ return level.getBlockState(belowPos).isFaceSturdy(level, belowPos, Direction.UP);
+ }
+
+ @Override
+ protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
+ Direction supportDirection = state.getValue(HANGING) ? Direction.UP : Direction.DOWN;
+ if (direction == supportDirection && !state.canSurvive(level, pos)) {
+ return Blocks.AIR.defaultBlockState();
+ }
+
+ return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
+ }
+
+ @Override
+ public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
+ if (random.nextInt(10) != 0) {
+ return;
+ }
+
+ double x = pos.getX() + 0.5D + (random.nextDouble() - 0.5D) * 0.6D;
+ double z = pos.getZ() + 0.5D + (random.nextDouble() - 0.5D) * 0.6D;
+ double y = state.getValue(HANGING) ? pos.getY() + 0.2D : pos.getY() + 0.8D;
+ double motionY = state.getValue(HANGING) ? -0.02D : 0.015D;
+ level.addParticle(new DustParticleOptions(POLLEN_COLOR, 1.0F), x, y, z, 0.0D, motionY, 0.0D);
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/block/SeashellBlock.java b/common/src/main/java/com/craisinlord/antarchy/content/block/SeashellBlock.java
new file mode 100644
index 00000000..8c6439c3
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/block/SeashellBlock.java
@@ -0,0 +1,240 @@
+package com.craisinlord.antarchy.content.block;
+
+import com.craisinlord.antarchy.content.AntarchyObjects;
+import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
+import com.mojang.serialization.MapCodec;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.ItemInteractionResult;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.LevelAccessor;
+import net.minecraft.world.level.LevelReader;
+import net.minecraft.world.level.block.BaseEntityBlock;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.EntityBlock;
+import net.minecraft.world.level.block.HorizontalDirectionalBlock;
+import net.minecraft.world.level.block.RenderShape;
+import net.minecraft.world.level.block.SimpleWaterloggedBlock;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.BlockEntityTicker;
+import net.minecraft.world.level.block.entity.BlockEntityType;
+import net.minecraft.world.level.block.state.BlockBehaviour;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.block.state.StateDefinition;
+import net.minecraft.world.level.block.state.properties.BlockStateProperties;
+import net.minecraft.world.level.block.state.properties.BooleanProperty;
+import net.minecraft.world.level.block.state.properties.DirectionProperty;
+import net.minecraft.world.level.material.FluidState;
+import net.minecraft.world.level.material.Fluids;
+import net.minecraft.world.phys.BlockHitResult;
+import net.minecraft.world.phys.shapes.CollisionContext;
+import net.minecraft.world.phys.shapes.VoxelShape;
+import org.jetbrains.annotations.Nullable;
+
+public final class SeashellBlock extends BaseEntityBlock implements SimpleWaterloggedBlock {
+ public static final MapCodec CODEC = Block.simpleCodec(SeashellBlock::new);
+ public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
+ public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
+ public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
+
+ private static final VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 5.333333D, 15.0D);
+
+ public SeashellBlock(BlockBehaviour.Properties properties) {
+ super(properties);
+ this.registerDefaultState(this.stateDefinition.any()
+ .setValue(FACING, Direction.NORTH)
+ .setValue(POWERED, false)
+ .setValue(WATERLOGGED, false));
+ }
+
+ @Override
+ public MapCodec codec() {
+ return CODEC;
+ }
+
+ @Override
+ protected void createBlockStateDefinition(StateDefinition.Builder builder) {
+ builder.add(FACING, POWERED, WATERLOGGED);
+ }
+
+ @Override
+ public BlockState getStateForPlacement(BlockPlaceContext context) {
+ FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos());
+ boolean powered = context.getLevel().hasNeighborSignal(context.getClickedPos());
+ return this.defaultBlockState()
+ .setValue(FACING, context.getHorizontalDirection().getOpposite())
+ .setValue(POWERED, powered)
+ .setValue(WATERLOGGED, fluidState.getType() == Fluids.WATER);
+ }
+
+ @Override
+ protected RenderShape getRenderShape(BlockState state) {
+ return RenderShape.ENTITYBLOCK_ANIMATED;
+ }
+
+ @Override
+ protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
+ return SHAPE;
+ }
+
+ @Override
+ protected VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
+ return SHAPE;
+ }
+
+ @Override
+ protected VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) {
+ return SHAPE;
+ }
+
+ @Override
+ protected BlockState rotate(BlockState state, net.minecraft.world.level.block.Rotation rotation) {
+ return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
+ }
+
+ @Override
+ protected BlockState mirror(BlockState state, net.minecraft.world.level.block.Mirror mirror) {
+ return state.rotate(mirror.getRotation(state.getValue(FACING)));
+ }
+
+ @Override
+ protected FluidState getFluidState(BlockState state) {
+ return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
+ }
+
+ @Override
+ protected BlockState updateShape(
+ BlockState state,
+ Direction direction,
+ BlockState neighborState,
+ LevelAccessor level,
+ BlockPos pos,
+ BlockPos neighborPos
+ ) {
+ if (state.getValue(WATERLOGGED)) {
+ level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
+ }
+
+ if (!state.canSurvive(level, pos)) {
+ return Blocks.AIR.defaultBlockState();
+ }
+
+ if (level instanceof Level actualLevel && !actualLevel.isClientSide) {
+ this.updatePowerState(actualLevel, pos, state);
+ }
+
+ return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
+ }
+
+ @Override
+ protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
+ return level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP);
+ }
+
+ @Override
+ protected void neighborChanged(
+ BlockState state,
+ Level level,
+ BlockPos pos,
+ Block block,
+ BlockPos neighborPos,
+ boolean movedByPiston
+ ) {
+ super.neighborChanged(state, level, pos, block, neighborPos, movedByPiston);
+ if (!level.isClientSide) {
+ this.updatePowerState(level, pos, state);
+ }
+ }
+
+ @Override
+ protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
+ super.onPlace(state, level, pos, oldState, movedByPiston);
+ if (!level.isClientSide) {
+ this.updatePowerState(level, pos, state);
+ }
+ }
+
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (!state.is(newState.getBlock()) && level.getBlockEntity(pos) instanceof SeashellBlockEntity seashell) {
+ seashell.dropContents(level, pos);
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+
+ @Override
+ protected ItemInteractionResult useItemOn(
+ ItemStack stack,
+ BlockState state,
+ Level level,
+ BlockPos pos,
+ Player player,
+ InteractionHand hand,
+ BlockHitResult hitResult
+ ) {
+ if (!(level.getBlockEntity(pos) instanceof SeashellBlockEntity seashell)) {
+ return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
+ }
+
+ if (!stack.isEmpty()) {
+ if (level.isClientSide) {
+ return seashell.canAcceptItem(player, stack) ? ItemInteractionResult.SUCCESS : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
+ }
+
+ if (seashell.tryInsert(player, hand, stack)) {
+ level.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.6F, 0.95F + level.random.nextFloat() * 0.1F);
+ return ItemInteractionResult.CONSUME;
+ }
+
+ return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
+ }
+
+ if (level.isClientSide) {
+ return seashell.hasAnyContents() ? ItemInteractionResult.SUCCESS : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
+ }
+
+ if (seashell.tryRemove(player, hand)) {
+ level.playSound(null, pos, SoundEvents.ITEM_FRAME_REMOVE_ITEM, SoundSource.BLOCKS, 0.6F, 0.95F + level.random.nextFloat() * 0.1F);
+ return ItemInteractionResult.CONSUME;
+ }
+
+ return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
+ }
+
+ @Override
+ public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
+ return new SeashellBlockEntity(pos, state);
+ }
+
+ @Override
+ public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) {
+ return level.isClientSide
+ ? createTickerHelper(blockEntityType, AntarchyObjects.SEASHELL_BLOCK_ENTITY.get(), SeashellBlockEntity::clientTick)
+ : createTickerHelper(blockEntityType, AntarchyObjects.SEASHELL_BLOCK_ENTITY.get(), SeashellBlockEntity::serverTick);
+ }
+
+ private void updatePowerState(Level level, BlockPos pos, BlockState state) {
+ boolean powered = level.hasNeighborSignal(pos);
+ if (state.getValue(POWERED) == powered) {
+ if (level.getBlockEntity(pos) instanceof SeashellBlockEntity seashell) {
+ seashell.syncVisualState(powered);
+ }
+ return;
+ }
+
+ BlockState updatedState = state.setValue(POWERED, powered);
+ level.setBlock(pos, updatedState, Block.UPDATE_ALL);
+ if (level.getBlockEntity(pos) instanceof SeashellBlockEntity seashell) {
+ seashell.onPowerStateChanged(powered);
+ }
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/block/entity/SeashellBlockEntity.java b/common/src/main/java/com/craisinlord/antarchy/content/block/entity/SeashellBlockEntity.java
new file mode 100644
index 00000000..b2367c28
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/block/entity/SeashellBlockEntity.java
@@ -0,0 +1,261 @@
+package com.craisinlord.antarchy.content.block.entity;
+
+import com.craisinlord.antarchy.content.AntarchyObjects;
+import com.craisinlord.antarchy.content.block.SeashellBlock;
+import java.util.ArrayList;
+import java.util.List;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
+import net.minecraft.core.HolderLookup;
+import net.minecraft.core.NonNullList;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.network.chat.Component;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.Containers;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.entity.player.Inventory;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.inventory.AbstractContainerMenu;
+import net.minecraft.world.inventory.ChestMenu;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.phys.Vec3;
+import org.jetbrains.annotations.Nullable;
+import software.bernie.geckolib.animatable.GeoBlockEntity;
+import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
+import software.bernie.geckolib.animation.AnimatableManager;
+import software.bernie.geckolib.animation.AnimationController;
+import software.bernie.geckolib.animation.PlayState;
+import software.bernie.geckolib.animation.RawAnimation;
+import software.bernie.geckolib.util.GeckoLibUtil;
+
+public final class SeashellBlockEntity extends RandomizableContainerBlockEntity implements GeoBlockEntity {
+ private static final String MAIN_CONTROLLER = "main_controller";
+ private static final String TRANSITION_CONTROLLER = "transition_controller";
+ private static final String OPEN_TRIGGER = "close_to_open";
+ private static final String CLOSE_TRIGGER = "open_to_close";
+ private static final RawAnimation OPEN_ANIM = RawAnimation.begin().thenPlayAndHold("open");
+ private static final RawAnimation CLOSED_ANIM = RawAnimation.begin().thenPlayAndHold("closed");
+ private static final Component TITLE = Component.translatable("block.antarchy.seashell");
+
+ private final AnimatableInstanceCache animatableCache = GeckoLibUtil.createInstanceCache(this);
+ private NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY);
+ private boolean visualOpen;
+ private boolean initializedVisualState;
+
+ public SeashellBlockEntity(BlockPos pos, BlockState blockState) {
+ super(AntarchyObjects.SEASHELL_BLOCK_ENTITY.get(), pos, blockState);
+ this.visualOpen = blockState.getValue(SeashellBlock.POWERED);
+ }
+
+ public static void serverTick(Level level, BlockPos pos, BlockState state, SeashellBlockEntity seashell) {
+ seashell.syncVisualState(state.getValue(SeashellBlock.POWERED));
+ }
+
+ public static void clientTick(Level level, BlockPos pos, BlockState state, SeashellBlockEntity seashell) {
+ seashell.syncVisualState(state.getValue(SeashellBlock.POWERED));
+ }
+
+ public boolean canAcceptItem(@Nullable Player player, ItemStack stack) {
+ this.unpackLootTable(player);
+ return !stack.isEmpty() && this.getFirstEmptySlot() >= 0;
+ }
+
+ public boolean tryInsert(@Nullable Player player, InteractionHand hand, ItemStack heldStack) {
+ this.unpackLootTable(player);
+ int slot = this.getFirstEmptySlot();
+ if (slot < 0 || heldStack.isEmpty()) {
+ return false;
+ }
+
+ ItemStack inserted = heldStack.copyWithCount(1);
+ this.items.set(slot, inserted);
+ if (player == null || !player.getAbilities().instabuild) {
+ heldStack.shrink(1);
+ }
+
+ this.setChangedAndSync();
+ return true;
+ }
+
+ public boolean tryRemove(Player player, InteractionHand hand) {
+ this.unpackLootTable(player);
+ int slot = this.getLastFilledSlot();
+ if (slot < 0) {
+ return false;
+ }
+
+ ItemStack removed = this.items.get(slot);
+ this.items.set(slot, ItemStack.EMPTY);
+ if (player.getItemInHand(hand).isEmpty()) {
+ player.setItemInHand(hand, removed);
+ } else if (!player.addItem(removed)) {
+ player.drop(removed, false);
+ }
+
+ this.setChangedAndSync();
+ return true;
+ }
+
+ public boolean hasAnyContents() {
+ return this.items.stream().anyMatch(stack -> !stack.isEmpty());
+ }
+
+ public void dropContents(Level level, BlockPos pos) {
+ this.unpackLootTable(null);
+ Containers.dropContents(level, pos, this.items);
+ this.items = NonNullList.withSize(9, ItemStack.EMPTY);
+ this.setChanged();
+ }
+
+ public void onPowerStateChanged(boolean open) {
+ this.syncVisualState(open);
+ this.triggerAnim(TRANSITION_CONTROLLER, open ? OPEN_TRIGGER : CLOSE_TRIGGER);
+ this.setChangedAndSync();
+ }
+
+ public void syncVisualState(boolean open) {
+ if (!this.initializedVisualState) {
+ this.visualOpen = open;
+ this.initializedVisualState = true;
+ return;
+ }
+
+ this.visualOpen = open;
+ }
+
+ public boolean isVisualOpen() {
+ return this.visualOpen;
+ }
+
+ public List getDisplayedStacks() {
+ List inserted = new ArrayList<>();
+ for (ItemStack stack : this.items) {
+ if (!stack.isEmpty()) {
+ inserted.add(stack);
+ }
+ }
+
+ List displayed = new ArrayList<>(inserted.size());
+ for (int i = 0; i < inserted.size(); i++) {
+ displayed.add(new DisplayedStack(inserted.get(i), displayOffsetFor(i)));
+ }
+ return displayed;
+ }
+
+ @Override
+ public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
+ controllers.add(new AnimationController<>(this, MAIN_CONTROLLER, state ->
+ state.setAndContinue(this.visualOpen ? OPEN_ANIM : CLOSED_ANIM)));
+ controllers.add(new AnimationController<>(this, TRANSITION_CONTROLLER, state -> PlayState.STOP)
+ .triggerableAnim(OPEN_TRIGGER, RawAnimation.begin().thenPlay(OPEN_TRIGGER))
+ .triggerableAnim(CLOSE_TRIGGER, RawAnimation.begin().thenPlay(CLOSE_TRIGGER)));
+ }
+
+ @Override
+ public AnimatableInstanceCache getAnimatableInstanceCache() {
+ return this.animatableCache;
+ }
+
+ @Override
+ protected Component getDefaultName() {
+ return TITLE;
+ }
+
+ @Override
+ protected NonNullList getItems() {
+ return this.items;
+ }
+
+ @Override
+ protected void setItems(NonNullList items) {
+ this.items = items;
+ }
+
+ @Override
+ protected AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
+ return ChestMenu.threeRows(containerId, inventory, this);
+ }
+
+ @Override
+ public int getMaxStackSize() {
+ return 1;
+ }
+
+ @Override
+ public boolean canPlaceItem(int slot, ItemStack stack) {
+ return !stack.isEmpty() && this.items.get(slot).isEmpty();
+ }
+
+ @Override
+ public int getContainerSize() {
+ return this.items.size();
+ }
+
+ @Override
+ protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
+ super.saveAdditional(tag, registries);
+ tag.putBoolean("VisualOpen", this.visualOpen);
+ tag.putBoolean("VisualInitialized", this.initializedVisualState);
+ }
+
+ @Override
+ protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
+ super.loadAdditional(tag, registries);
+ this.visualOpen = tag.getBoolean("VisualOpen");
+ this.initializedVisualState = tag.getBoolean("VisualInitialized");
+ }
+
+ private void setChangedAndSync() {
+ this.setChanged();
+ if (this.level != null) {
+ BlockState state = this.getBlockState();
+ this.level.sendBlockUpdated(this.worldPosition, state, state, Block.UPDATE_CLIENTS);
+ }
+ }
+
+ private int getFirstEmptySlot() {
+ for (int i = 0; i < this.items.size(); i++) {
+ if (this.items.get(i).isEmpty()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int getLastFilledSlot() {
+ for (int i = this.items.size() - 1; i >= 0; i--) {
+ if (!this.items.get(i).isEmpty()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private static Vec3 displayOffsetFor(int insertionIndex) {
+ return switch (insertionIndex) {
+ case 0 -> offset(1, 0);
+ case 1 -> offset(0, 0);
+ case 2 -> offset(2, 0);
+ case 3 -> offset(1, 1);
+ case 4 -> offset(0, 1);
+ case 5 -> offset(2, 1);
+ case 6 -> offset(1, 2);
+ case 7 -> offset(0, 2);
+ case 8 -> offset(2, 2);
+ default -> Vec3.ZERO;
+ };
+ }
+
+ private static Vec3 offset(int column, int row) {
+ double x = -0.22D + column * 0.22D;
+ double z = -0.22D + row * 0.22D;
+ return new Vec3(x, 0.155D, z);
+ }
+
+ public record DisplayedStack(ItemStack stack, Vec3 offset) {
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/client/model/KrakensGraspThrownTridentModel.java b/common/src/main/java/com/craisinlord/antarchy/content/client/model/KrakensGraspThrownTridentModel.java
new file mode 100644
index 00000000..c5fced09
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/client/model/KrakensGraspThrownTridentModel.java
@@ -0,0 +1,22 @@
+package com.craisinlord.antarchy.content.client.model;
+
+import com.craisinlord.antarchy.content.entity.kraken.KrakensGraspThrownTrident;
+import net.minecraft.resources.ResourceLocation;
+import software.bernie.geckolib.model.GeoModel;
+
+public class KrakensGraspThrownTridentModel extends GeoModel {
+ @Override
+ public ResourceLocation getModelResource(KrakensGraspThrownTrident animatable) {
+ return ResourceLocation.fromNamespaceAndPath("antarchy", "geo/krakens_grasp.geo.json");
+ }
+
+ @Override
+ public ResourceLocation getTextureResource(KrakensGraspThrownTrident animatable) {
+ return ResourceLocation.fromNamespaceAndPath("antarchy", "textures/item/krakens_grasp/krakens_grasp.png");
+ }
+
+ @Override
+ public ResourceLocation getAnimationResource(KrakensGraspThrownTrident animatable) {
+ return ResourceLocation.fromNamespaceAndPath("antarchy", "animations/static_item.animation.json");
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/client/model/SeashellModel.java b/common/src/main/java/com/craisinlord/antarchy/content/client/model/SeashellModel.java
new file mode 100644
index 00000000..a678775a
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/client/model/SeashellModel.java
@@ -0,0 +1,27 @@
+package com.craisinlord.antarchy.content.client.model;
+
+import com.craisinlord.antarchy.Antarchy;
+import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
+import net.minecraft.resources.ResourceLocation;
+import software.bernie.geckolib.model.GeoModel;
+
+public final class SeashellModel extends GeoModel {
+ private static final ResourceLocation MODEL = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/seashell.geo.json");
+ private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/block/seashell.png");
+ private static final ResourceLocation ANIMATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/seashell.animation.json");
+
+ @Override
+ public ResourceLocation getModelResource(SeashellBlockEntity animatable) {
+ return MODEL;
+ }
+
+ @Override
+ public ResourceLocation getTextureResource(SeashellBlockEntity animatable) {
+ return TEXTURE;
+ }
+
+ @Override
+ public ResourceLocation getAnimationResource(SeashellBlockEntity animatable) {
+ return ANIMATION;
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/client/renderer/KrakensGraspThrownTridentRenderer.java b/common/src/main/java/com/craisinlord/antarchy/content/client/renderer/KrakensGraspThrownTridentRenderer.java
new file mode 100644
index 00000000..8f7ddd21
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/client/renderer/KrakensGraspThrownTridentRenderer.java
@@ -0,0 +1,13 @@
+package com.craisinlord.antarchy.content.client.renderer;
+
+import com.craisinlord.antarchy.content.client.model.KrakensGraspThrownTridentModel;
+import com.craisinlord.antarchy.content.entity.kraken.KrakensGraspThrownTrident;
+import net.minecraft.client.renderer.entity.EntityRendererProvider;
+import software.bernie.geckolib.renderer.GeoEntityRenderer;
+
+public class KrakensGraspThrownTridentRenderer extends GeoEntityRenderer {
+ public KrakensGraspThrownTridentRenderer(EntityRendererProvider.Context context) {
+ super(context, new KrakensGraspThrownTridentModel());
+ this.shadowRadius = 0.0F;
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/client/renderer/SeashellRenderer.java b/common/src/main/java/com/craisinlord/antarchy/content/client/renderer/SeashellRenderer.java
new file mode 100644
index 00000000..65cbc5a4
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/client/renderer/SeashellRenderer.java
@@ -0,0 +1,73 @@
+package com.craisinlord.antarchy.content.client.renderer;
+
+import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
+import com.craisinlord.antarchy.content.client.model.SeashellModel;
+import com.mojang.blaze3d.vertex.PoseStack;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
+import net.minecraft.core.Direction;
+import net.minecraft.world.item.ItemDisplayContext;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.phys.Vec3;
+import software.bernie.geckolib.cache.object.BakedGeoModel;
+import software.bernie.geckolib.renderer.GeoBlockRenderer;
+
+public final class SeashellRenderer extends GeoBlockRenderer {
+ public SeashellRenderer(BlockEntityRendererProvider.Context context) {
+ super(new SeashellModel());
+ }
+
+ @Override
+ public void actuallyRender(
+ PoseStack poseStack,
+ SeashellBlockEntity animatable,
+ BakedGeoModel model,
+ net.minecraft.client.renderer.RenderType renderType,
+ MultiBufferSource bufferSource,
+ com.mojang.blaze3d.vertex.VertexConsumer buffer,
+ boolean isReRender,
+ float partialTick,
+ int packedLight,
+ int packedOverlay,
+ int colour
+ ) {
+ super.actuallyRender(poseStack, animatable, model, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, colour);
+ if (isReRender) {
+ return;
+ }
+
+ float yaw = -animatable.getBlockState().getValue(com.craisinlord.antarchy.content.block.SeashellBlock.FACING).toYRot();
+ for (SeashellBlockEntity.DisplayedStack displayedStack : animatable.getDisplayedStacks()) {
+ this.renderDisplayItem(poseStack, bufferSource, displayedStack.stack(), displayedStack.offset(), yaw, packedLight, packedOverlay);
+ }
+ }
+
+ private void renderDisplayItem(
+ PoseStack poseStack,
+ MultiBufferSource bufferSource,
+ ItemStack stack,
+ Vec3 localOffset,
+ float yaw,
+ int packedLight,
+ int packedOverlay
+ ) {
+ poseStack.pushPose();
+ poseStack.translate(0.5D, 0.0D, 0.5D);
+ poseStack.mulPose(com.mojang.math.Axis.YP.rotationDegrees(yaw));
+ poseStack.translate(localOffset.x(), localOffset.y(), localOffset.z());
+ poseStack.mulPose(com.mojang.math.Axis.XP.rotationDegrees(90.0F));
+ poseStack.scale(0.22F, 0.22F, 0.22F);
+ Minecraft.getInstance().getItemRenderer().renderStatic(
+ stack,
+ ItemDisplayContext.FIXED,
+ packedLight,
+ packedOverlay,
+ poseStack,
+ bufferSource,
+ null,
+ 0
+ );
+ poseStack.popPose();
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakensGraspThrownTrident.java b/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakensGraspThrownTrident.java
index 240141ac..4dc20d41 100644
--- a/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakensGraspThrownTrident.java
+++ b/common/src/main/java/com/craisinlord/antarchy/content/entity/kraken/KrakensGraspThrownTrident.java
@@ -11,16 +11,20 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.AbstractArrow;
-import net.minecraft.world.entity.projectile.ItemSupplier;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
+import software.bernie.geckolib.animatable.GeoEntity;
+import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
+import software.bernie.geckolib.animation.AnimatableManager;
+import software.bernie.geckolib.util.GeckoLibUtil;
-public class KrakensGraspThrownTrident extends AbstractArrow implements ItemSupplier {
+public class KrakensGraspThrownTrident extends AbstractArrow implements GeoEntity {
private boolean dealtDamage;
private boolean returning;
+ private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
public KrakensGraspThrownTrident(EntityType extends KrakensGraspThrownTrident> entityType, Level level) {
super(entityType, level);
@@ -32,8 +36,12 @@ public class KrakensGraspThrownTrident extends AbstractArrow implements ItemSupp
}
@Override
- public ItemStack getItem() {
- return new ItemStack(AntarchyObjects.KRAKENS_GRASP.get());
+ public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
+ }
+
+ @Override
+ public AnimatableInstanceCache getAnimatableInstanceCache() {
+ return this.geoCache;
}
@Override
@@ -94,6 +102,8 @@ public class KrakensGraspThrownTrident extends AbstractArrow implements ItemSupp
boolean hurt = target.hurt(damageSource, (float) AntarchySettings.krakensGraspThrownDamage());
if (hurt) {
KrakensGraspItem.strikeLightning(target, serverLevel);
+ TentacleEntity.spawnAt(serverLevel, new Vec3(target.getX(), target.getY(), target.getZ()),
+ owner instanceof LivingEntity livingOwner ? livingOwner : null);
}
this.dealtDamage = true;
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/item/KrakensGraspItem.java b/common/src/main/java/com/craisinlord/antarchy/content/item/KrakensGraspItem.java
index 51a44d3d..5d44a35a 100644
--- a/common/src/main/java/com/craisinlord/antarchy/content/item/KrakensGraspItem.java
+++ b/common/src/main/java/com/craisinlord/antarchy/content/item/KrakensGraspItem.java
@@ -58,11 +58,6 @@ public class KrakensGraspItem extends TridentItem implements GeoItem {
.build();
}
- @Override
- public net.minecraft.world.item.UseAnim getUseAnimation(ItemStack stack) {
- return net.minecraft.world.item.UseAnim.NONE;
- }
-
@Override
public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) {
super.inventoryTick(stack, level, entity, slotId, isSelected);
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/GiantLilyPadPatchFeature.java b/common/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/GiantLilyPadPatchFeature.java
new file mode 100644
index 00000000..ecf972d8
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/GiantLilyPadPatchFeature.java
@@ -0,0 +1,101 @@
+package com.craisinlord.antarchy.content.worldgen.elythia;
+
+import com.craisinlord.antarchy.content.AntarchyObjects;
+import com.mojang.serialization.Codec;
+import net.minecraft.core.BlockPos;
+import net.minecraft.tags.FluidTags;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.level.WorldGenLevel;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.levelgen.Heightmap;
+import net.minecraft.world.level.levelgen.feature.Feature;
+import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
+import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class GiantLilyPadPatchFeature extends Feature {
+ public GiantLilyPadPatchFeature(Codec codec) {
+ super(codec);
+ }
+
+ @Override
+ public boolean place(FeaturePlaceContext context) {
+ WorldGenLevel level = context.level();
+ RandomSource random = context.random();
+ BlockPos origin = context.origin();
+ boolean placedAny = false;
+
+ for (int i = 0; i < 12; i++) {
+ int anchorX = origin.getX() + random.nextInt(17) - 8;
+ int anchorZ = origin.getZ() + random.nextInt(17) - 8;
+ int surfaceY = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, anchorX, anchorZ) - 1;
+ BlockPos anchorFluidPos = new BlockPos(anchorX, surfaceY, anchorZ);
+ if (!level.getFluidState(anchorFluidPos).is(FluidTags.WATER) || !level.getFluidState(anchorFluidPos).isSource()) {
+ continue;
+ }
+
+ int size = rollFootprintSize(random);
+ List footprint = new ArrayList<>(size * size);
+ boolean valid = true;
+ for (int row = 0; row < size && valid; row++) {
+ for (int column = 0; column < size; column++) {
+ BlockPos fluidPos = new BlockPos(anchorX + column, surfaceY, anchorZ + row);
+ if (!level.getFluidState(fluidPos).is(FluidTags.WATER) || !level.getFluidState(fluidPos).isSource()) {
+ valid = false;
+ break;
+ }
+
+ BlockPos padPos = fluidPos.above();
+ if (!level.isEmptyBlock(padPos)) {
+ valid = false;
+ break;
+ }
+
+ footprint.add(padPos);
+ }
+ }
+
+ if (!valid) {
+ continue;
+ }
+
+ Block giantLilyPad = AntarchyObjects.GIANT_LILY_PAD.get();
+ BlockState padState = giantLilyPad.defaultBlockState();
+ for (BlockPos padPos : footprint) {
+ level.setBlock(padPos, padState, Block.UPDATE_ALL);
+ }
+
+ placedAny = true;
+
+ if (size == 3 && random.nextFloat() < 0.5F) {
+ BlockPos centerPos = new BlockPos(anchorX + 1, surfaceY, anchorZ + 1).above();
+ placeLotus(level, centerPos.above());
+ }
+ }
+
+ return placedAny;
+ }
+
+ private static int rollFootprintSize(RandomSource random) {
+ float roll = random.nextFloat();
+ if (roll < 0.5F) {
+ return 1;
+ }
+
+ return roll < 0.8F ? 2 : 3;
+ }
+
+ private void placeLotus(WorldGenLevel level, BlockPos pos) {
+ if (!level.isEmptyBlock(pos)) {
+ return;
+ }
+
+ BlockState lotusState = AntarchyObjects.LOTUS.get().defaultBlockState();
+ if (lotusState.canSurvive(level, pos)) {
+ level.setBlock(pos, lotusState, Block.UPDATE_ALL);
+ }
+ }
+}
diff --git a/common/src/main/java/com/craisinlord/antarchy/content/worldgen/ocean/SeashellFeature.java b/common/src/main/java/com/craisinlord/antarchy/content/worldgen/ocean/SeashellFeature.java
new file mode 100644
index 00000000..e0a83d83
--- /dev/null
+++ b/common/src/main/java/com/craisinlord/antarchy/content/worldgen/ocean/SeashellFeature.java
@@ -0,0 +1,65 @@
+package com.craisinlord.antarchy.content.worldgen.ocean;
+
+import com.craisinlord.antarchy.Antarchy;
+import com.craisinlord.antarchy.content.AntarchyObjects;
+import com.craisinlord.antarchy.content.block.SeashellBlock;
+import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
+import com.mojang.serialization.Codec;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.registries.Registries;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.level.WorldGenLevel;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.storage.loot.LootTable;
+import net.minecraft.world.level.levelgen.Heightmap;
+import net.minecraft.world.level.levelgen.feature.Feature;
+import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
+import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
+
+public final class SeashellFeature extends Feature {
+ private static final ResourceKey LOOT_TABLE = ResourceKey.create(
+ Registries.LOOT_TABLE,
+ ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "chests/seashell")
+ );
+
+ public SeashellFeature(Codec codec) {
+ super(codec);
+ }
+
+ @Override
+ public boolean place(FeaturePlaceContext context) {
+ WorldGenLevel level = context.level();
+ RandomSource random = context.random();
+ BlockPos origin = context.origin();
+ boolean placedAny = false;
+
+ for (int i = 0; i < 8; i++) {
+ int x = origin.getX() + random.nextInt(17) - 8;
+ int z = origin.getZ() + random.nextInt(17) - 8;
+ int floorY = level.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, x, z);
+ BlockPos shellPos = new BlockPos(x, floorY, z);
+
+ if (!level.getFluidState(shellPos).isSource()) {
+ continue;
+ }
+
+ BlockState state = AntarchyObjects.SEASHELL.get().defaultBlockState()
+ .setValue(SeashellBlock.FACING, net.minecraft.core.Direction.Plane.HORIZONTAL.getRandomDirection(random))
+ .setValue(SeashellBlock.WATERLOGGED, true)
+ .setValue(SeashellBlock.POWERED, false);
+ if (!state.canSurvive(level, shellPos)) {
+ continue;
+ }
+
+ level.setBlock(shellPos, state, 2);
+ if (level.getBlockEntity(shellPos) instanceof SeashellBlockEntity seashell) {
+ seashell.setLootTable(LOOT_TABLE, random.nextLong());
+ }
+ placedAny = true;
+ }
+
+ return placedAny;
+ }
+}
diff --git a/common/src/main/resources/assets/antarchy/animations/seashell.animation.json b/common/src/main/resources/assets/antarchy/animations/seashell.animation.json
new file mode 100644
index 00000000..c97e7f6b
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/animations/seashell.animation.json
@@ -0,0 +1,62 @@
+{
+ "format_version": "1.8.0",
+ "animations": {
+ "close_to_open": {
+ "loop": "hold_on_last_frame",
+ "animation_length": 0.375,
+ "bones": {
+ "upper_moving": {
+ "rotation": {
+ "0.0": {
+ "vector": [0, 0, 0]
+ },
+ "0.375": {
+ "vector": [-90, 0, 0],
+ "easing": "easeOutBack"
+ }
+ }
+ }
+ }
+ },
+ "closed": {
+ "loop": "hold_on_last_frame",
+ "bones": {
+ "upper_moving": {
+ "rotation": {
+ "vector": [0, 0, 0]
+ }
+ }
+ }
+ },
+ "open_to_close": {
+ "loop": "hold_on_last_frame",
+ "animation_length": 0.4167,
+ "bones": {
+ "upper_moving": {
+ "rotation": {
+ "0.0": {
+ "vector": [-90, 0, 0],
+ "easing": "easeOutBack"
+ },
+ "0.4167": {
+ "vector": [0, 0, 0],
+ "easing": "easeInOutBack",
+ "easingArgs": [0.5]
+ }
+ }
+ }
+ }
+ },
+ "open": {
+ "loop": "hold_on_last_frame",
+ "bones": {
+ "upper_moving": {
+ "rotation": {
+ "vector": [-90, 0, 0],
+ "easing": "easeOutBack"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/resources/assets/antarchy/blockstates/lotus.json b/common/src/main/resources/assets/antarchy/blockstates/lotus.json
new file mode 100644
index 00000000..91b0e7f0
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/blockstates/lotus.json
@@ -0,0 +1,6 @@
+{
+ "variants": {
+ "hanging=false": { "model": "antarchy:block/lotus" },
+ "hanging=true": { "model": "antarchy:block/lotus", "x": 180 }
+ }
+}
diff --git a/common/src/main/resources/assets/antarchy/blockstates/seashell.json b/common/src/main/resources/assets/antarchy/blockstates/seashell.json
new file mode 100644
index 00000000..1e35228b
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/blockstates/seashell.json
@@ -0,0 +1,20 @@
+{
+ "variants": {
+ "facing=north,powered=false,waterlogged=false": { "model": "builtin/entity" },
+ "facing=north,powered=false,waterlogged=true": { "model": "builtin/entity" },
+ "facing=north,powered=true,waterlogged=false": { "model": "builtin/entity" },
+ "facing=north,powered=true,waterlogged=true": { "model": "builtin/entity" },
+ "facing=south,powered=false,waterlogged=false": { "model": "builtin/entity" },
+ "facing=south,powered=false,waterlogged=true": { "model": "builtin/entity" },
+ "facing=south,powered=true,waterlogged=false": { "model": "builtin/entity" },
+ "facing=south,powered=true,waterlogged=true": { "model": "builtin/entity" },
+ "facing=east,powered=false,waterlogged=false": { "model": "builtin/entity" },
+ "facing=east,powered=false,waterlogged=true": { "model": "builtin/entity" },
+ "facing=east,powered=true,waterlogged=false": { "model": "builtin/entity" },
+ "facing=east,powered=true,waterlogged=true": { "model": "builtin/entity" },
+ "facing=west,powered=false,waterlogged=false": { "model": "builtin/entity" },
+ "facing=west,powered=false,waterlogged=true": { "model": "builtin/entity" },
+ "facing=west,powered=true,waterlogged=false": { "model": "builtin/entity" },
+ "facing=west,powered=true,waterlogged=true": { "model": "builtin/entity" }
+ }
+}
diff --git a/common/src/main/resources/assets/antarchy/geo/seashell.geo.json b/common/src/main/resources/assets/antarchy/geo/seashell.geo.json
new file mode 100644
index 00000000..73910555
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/geo/seashell.geo.json
@@ -0,0 +1,173 @@
+{
+ "format_version": "1.12.0",
+ "minecraft:geometry": [
+ {
+ "description": {
+ "identifier": "geometry.unknown",
+ "texture_width": 64,
+ "texture_height": 64,
+ "visible_bounds_width": 3,
+ "visible_bounds_height": 2.5,
+ "visible_bounds_offset": [0, 0.75, 0]
+ },
+ "bones": [
+ {
+ "name": "seashell",
+ "pivot": [0, 0, 0]
+ },
+ {
+ "name": "lower",
+ "parent": "seashell",
+ "pivot": [0, 0, 0],
+ "cubes": [
+ {
+ "origin": [-7, 0, -7],
+ "size": [14, 2, 14],
+ "uv": {
+ "north": {"uv": [14, 15], "uv_size": [14, 2]},
+ "east": {"uv": [0, 15], "uv_size": [14, 2]},
+ "south": {"uv": [42, 15], "uv_size": [14, 2]},
+ "west": {"uv": [28, 15], "uv_size": [14, 2]},
+ "up": {"uv": [14, 0], "uv_size": [14, 14]},
+ "down": {"uv": [28, 14], "uv_size": [14, -14]}
+ }
+ },
+ {
+ "origin": [-7, 2, -7],
+ "size": [14, 1, 1],
+ "uv": {
+ "north": {"uv": [14, 14], "uv_size": [14, 1]},
+ "east": {"uv": [13, 14], "uv_size": [1, 1]},
+ "south": {"uv": [42, 14], "uv_size": [14, 1]},
+ "west": {"uv": [28, 14], "uv_size": [1, 1]},
+ "up": {"uv": [14, 0], "uv_size": [14, 1]},
+ "down": {"uv": [28, 14], "uv_size": [14, -14]}
+ }
+ },
+ {
+ "origin": [-7, 2, -6],
+ "size": [1, 1, 12],
+ "uv": {
+ "north": {"uv": [14, 14], "uv_size": [14, 1]},
+ "east": {"uv": [1, 14], "uv_size": [12, 1]},
+ "south": {"uv": [42, 14], "uv_size": [14, 1]},
+ "west": {"uv": [29, 14], "uv_size": [12, 1]},
+ "up": {"uv": [14, 1], "uv_size": [1, 12]},
+ "down": {"uv": [28, 14], "uv_size": [14, -14]}
+ }
+ },
+ {
+ "origin": [6, 2, -6],
+ "size": [1, 1, 12],
+ "uv": {
+ "north": {"uv": [14, 14], "uv_size": [14, 1]},
+ "east": {"uv": [1, 14], "uv_size": [12, 1]},
+ "south": {"uv": [42, 14], "uv_size": [14, 1]},
+ "west": {"uv": [29, 14], "uv_size": [12, 1]},
+ "up": {"uv": [27, 1], "uv_size": [1, 12]},
+ "down": {"uv": [28, 14], "uv_size": [14, -14]}
+ }
+ },
+ {
+ "origin": [-7, 2, 6],
+ "size": [14, 1, 1],
+ "uv": {
+ "north": {"uv": [14, 14], "uv_size": [14, 1]},
+ "east": {"uv": [13, 14], "uv_size": [1, 1]},
+ "south": {"uv": [42, 14], "uv_size": [14, 1]},
+ "west": {"uv": [28, 14], "uv_size": [1, 1]},
+ "up": {"uv": [14, 0], "uv_size": [14, 1]},
+ "down": {"uv": [28, 14], "uv_size": [14, -14]}
+ }
+ }
+ ]
+ },
+ {
+ "name": "upper_moving",
+ "parent": "seashell",
+ "pivot": [0, 2.5, 7],
+ "cubes": [
+ {
+ "origin": [-2, 1.5, 7],
+ "size": [4, 2, 1],
+ "inflate": 0.01,
+ "uv": {
+ "north": {"uv": [2, 34], "uv_size": [4, 2]},
+ "east": {"uv": [1, 34], "uv_size": [1, 2]},
+ "south": {"uv": [7, 34], "uv_size": [4, 2]},
+ "west": {"uv": [6, 34], "uv_size": [1, 2]},
+ "up": {"uv": [2, 33], "uv_size": [4, 1]},
+ "down": {"uv": [6, 34], "uv_size": [4, -1]}
+ }
+ },
+ {
+ "origin": [-7, 3.5, -7],
+ "size": [14, 1, 14],
+ "inflate": 0.01,
+ "uv": {
+ "north": {"uv": [14, 31], "uv_size": [14, 1]},
+ "east": {"uv": [0, 31], "uv_size": [14, 1]},
+ "south": {"uv": [42, 31], "uv_size": [14, 1]},
+ "west": {"uv": [28, 31], "uv_size": [14, 1]},
+ "up": {"uv": [14, 17], "uv_size": [14, 14]},
+ "down": {"uv": [28, 31], "uv_size": [14, -14]}
+ }
+ },
+ {
+ "origin": [-7, 2.5, 6],
+ "size": [14, 1, 1],
+ "inflate": 0.01,
+ "uv": {
+ "north": {"uv": [14, 14], "uv_size": [14, 1]},
+ "east": {"uv": [13, 14], "uv_size": [1, 1]},
+ "south": {"uv": [42, 14], "uv_size": [14, 1]},
+ "west": {"uv": [28, 14], "uv_size": [1, 1]},
+ "up": {"uv": [14, 0], "uv_size": [14, 1]},
+ "down": {"uv": [28, 1], "uv_size": [14, -1]}
+ }
+ },
+ {
+ "origin": [6, 2.5, -6],
+ "size": [1, 1, 12],
+ "inflate": 0.01,
+ "uv": {
+ "north": {"uv": [14, 14], "uv_size": [14, 1]},
+ "east": {"uv": [1, 14], "uv_size": [12, 1]},
+ "south": {"uv": [42, 14], "uv_size": [14, 1]},
+ "west": {"uv": [29, 32], "uv_size": [12, 1]},
+ "up": {"uv": [27, 1], "uv_size": [1, 12]},
+ "down": {"uv": [41, 13], "uv_size": [1, -12]}
+ }
+ },
+ {
+ "origin": [-7, 2.5, -7],
+ "size": [14, 1, 1],
+ "inflate": 0.01,
+ "uv": {
+ "north": {"uv": [14, 32], "uv_size": [14, 1]},
+ "east": {"uv": [13, 14], "uv_size": [1, 1]},
+ "south": {"uv": [42, 32], "uv_size": [14, 1]},
+ "west": {"uv": [28, 32], "uv_size": [1, 1]},
+ "up": {"uv": [14, 0], "uv_size": [14, 1]},
+ "down": {"uv": [28, 1], "uv_size": [14, -1]}
+ }
+ },
+ {
+ "origin": [-7, 2.5, -6],
+ "size": [1, 1, 12],
+ "inflate": 0.01,
+ "uv": {
+ "north": {"uv": [14, 14], "uv_size": [14, 1]},
+ "east": {"uv": [1, 32], "uv_size": [12, 1]},
+ "south": {"uv": [42, 14], "uv_size": [14, 1]},
+ "west": {"uv": [29, 14], "uv_size": [12, 1]},
+ "up": {"uv": [14, 1], "uv_size": [1, 12]},
+ "down": {"uv": [28, 13], "uv_size": [1, -12]}
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/common/src/main/resources/assets/antarchy/lang/en_us.json b/common/src/main/resources/assets/antarchy/lang/en_us.json
index c340bff9..55597be8 100644
--- a/common/src/main/resources/assets/antarchy/lang/en_us.json
+++ b/common/src/main/resources/assets/antarchy/lang/en_us.json
@@ -41,7 +41,10 @@
"block.antarchy.pink_milkweed": "Pink Milkweed",
"block.antarchy.camellia": "Camellia",
"block.antarchy.spider_lily": "Spider Lily",
+ "block.antarchy.lotus": "Lotus",
+ "item.antarchy.lotus": "Lotus",
"block.antarchy.giant_lily_pad": "Giant Lily Pad",
+ "block.antarchy.seashell": "Seashell",
"block.antarchy.hushweed": "Hushweed",
"block.antarchy.umbral_moss_block": "Umbral Moss Block",
"block.antarchy.umbral_moss_carpet": "Umbral Moss Carpet",
@@ -233,6 +236,7 @@
"item.antarchy.dream_lantern": "Dream Lantern",
"item.antarchy.dream_campfire": "Dream Campfire",
"item.antarchy.giant_lily_pad": "Giant Lily Pad",
+ "item.antarchy.seashell": "Seashell",
"item.antarchy.nightmare_scale": "Nightmare Scale",
"item.antarchy.nightmare_helmet": "Nightmare Helmet",
"item.antarchy.nightmare_chestplate": "Nightmare Chestplate",
diff --git a/common/src/main/resources/assets/antarchy/models/block/lotus.json b/common/src/main/resources/assets/antarchy/models/block/lotus.json
new file mode 100644
index 00000000..a1b802d2
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/models/block/lotus.json
@@ -0,0 +1,6 @@
+{
+ "parent": "minecraft:block/cross",
+ "textures": {
+ "cross": "antarchy:block/lotus"
+ }
+}
diff --git a/common/src/main/resources/assets/antarchy/models/item/cheep.json b/common/src/main/resources/assets/antarchy/models/item/cheep.json
new file mode 100644
index 00000000..4429a18f
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/models/item/cheep.json
@@ -0,0 +1,6 @@
+{
+ "parent": "minecraft:item/generated",
+ "textures": {
+ "layer0": "antarchy:item/cheep"
+ }
+}
diff --git a/common/src/main/resources/assets/antarchy/models/item/lotus.json b/common/src/main/resources/assets/antarchy/models/item/lotus.json
new file mode 100644
index 00000000..2e3e72b7
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/models/item/lotus.json
@@ -0,0 +1,6 @@
+{
+ "parent": "minecraft:item/generated",
+ "textures": {
+ "layer0": "antarchy:block/lotus"
+ }
+}
diff --git a/common/src/main/resources/assets/antarchy/models/item/seashell.json b/common/src/main/resources/assets/antarchy/models/item/seashell.json
new file mode 100644
index 00000000..48b6692a
--- /dev/null
+++ b/common/src/main/resources/assets/antarchy/models/item/seashell.json
@@ -0,0 +1,6 @@
+{
+ "parent": "minecraft:item/generated",
+ "textures": {
+ "layer0": "antarchy:block/seashell"
+ }
+}
diff --git a/common/src/main/resources/assets/antarchy/textures/block/seashell.png b/common/src/main/resources/assets/antarchy/textures/block/seashell.png
new file mode 100644
index 00000000..4c957b83
Binary files /dev/null and b/common/src/main/resources/assets/antarchy/textures/block/seashell.png differ
diff --git a/common/src/main/resources/data/antarchy/loot_table/blocks/lotus.json b/common/src/main/resources/data/antarchy/loot_table/blocks/lotus.json
new file mode 100644
index 00000000..2c7f5cb8
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/loot_table/blocks/lotus.json
@@ -0,0 +1,18 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1.0,
+ "conditions": [
+ { "condition": "minecraft:survives_explosion" }
+ ],
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "antarchy:lotus"
+ }
+ ]
+ }
+ ],
+ "random_sequence": "antarchy:blocks/lotus"
+}
diff --git a/common/src/main/resources/data/antarchy/loot_table/blocks/seashell.json b/common/src/main/resources/data/antarchy/loot_table/blocks/seashell.json
new file mode 100644
index 00000000..da9adf20
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/loot_table/blocks/seashell.json
@@ -0,0 +1,19 @@
+{
+ "type": "minecraft:block",
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "antarchy:seashell"
+ }
+ ],
+ "conditions": [
+ {
+ "condition": "minecraft:survives_explosion"
+ }
+ ]
+ }
+ ]
+}
diff --git a/common/src/main/resources/data/antarchy/loot_table/chests/seashell.json b/common/src/main/resources/data/antarchy/loot_table/chests/seashell.json
new file mode 100644
index 00000000..047f84e5
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/loot_table/chests/seashell.json
@@ -0,0 +1,23 @@
+{
+ "type": "minecraft:chest",
+ "pools": [
+ {
+ "rolls": {
+ "type": "minecraft:uniform",
+ "min": 2,
+ "max": 5
+ },
+ "entries": [
+ { "type": "minecraft:item", "name": "minecraft:nautilus_shell", "weight": 8 },
+ { "type": "minecraft:item", "name": "minecraft:prismarine_shard", "weight": 10 },
+ { "type": "minecraft:item", "name": "minecraft:prismarine_crystals", "weight": 8 },
+ { "type": "minecraft:item", "name": "minecraft:kelp", "weight": 12 },
+ { "type": "minecraft:item", "name": "minecraft:seagrass", "weight": 10 },
+ { "type": "minecraft:item", "name": "minecraft:tropical_fish", "weight": 4 },
+ { "type": "minecraft:item", "name": "minecraft:bone_meal", "weight": 8 },
+ { "type": "minecraft:item", "name": "antarchy:star_coral", "weight": 3 },
+ { "type": "minecraft:item", "name": "antarchy:giant_lily_pad", "weight": 1 }
+ ]
+ }
+ ]
+}
diff --git a/common/src/main/resources/data/antarchy/loot_table/entities/cheep.json b/common/src/main/resources/data/antarchy/loot_table/entities/cheep.json
index 9c830ca5..ea3b5bba 100644
--- a/common/src/main/resources/data/antarchy/loot_table/entities/cheep.json
+++ b/common/src/main/resources/data/antarchy/loot_table/entities/cheep.json
@@ -1,5 +1,15 @@
{
"type": "minecraft:entity",
- "pools": [],
+ "pools": [
+ {
+ "rolls": 1,
+ "entries": [
+ {
+ "type": "minecraft:item",
+ "name": "antarchy:cheep"
+ }
+ ]
+ }
+ ],
"random_sequence": "antarchy:entities/cheep"
}
diff --git a/common/src/main/resources/data/antarchy/recipe/pink_dye_from_lotus.json b/common/src/main/resources/data/antarchy/recipe/pink_dye_from_lotus.json
new file mode 100644
index 00000000..e3a7b1a3
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/recipe/pink_dye_from_lotus.json
@@ -0,0 +1,11 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "category": "misc",
+ "ingredients": [
+ { "item": "antarchy:lotus" }
+ ],
+ "result": {
+ "count": 2,
+ "id": "minecraft:pink_dye"
+ }
+}
diff --git a/common/src/main/resources/data/antarchy/tags/worldgen/biome/has_seashell.json b/common/src/main/resources/data/antarchy/tags/worldgen/biome/has_seashell.json
new file mode 100644
index 00000000..d70e35cc
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/tags/worldgen/biome/has_seashell.json
@@ -0,0 +1,14 @@
+{
+ "replace": false,
+ "values": [
+ "#minecraft:is_ocean",
+ {
+ "id": "#neoforge:is_ocean",
+ "required": false
+ },
+ {
+ "id": "#c:ocean",
+ "required": false
+ }
+ ]
+}
diff --git a/common/src/main/resources/data/antarchy/worldgen/biome/elythia_ocean.json b/common/src/main/resources/data/antarchy/worldgen/biome/elythia_ocean.json
index da24502b..95764482 100644
--- a/common/src/main/resources/data/antarchy/worldgen/biome/elythia_ocean.json
+++ b/common/src/main/resources/data/antarchy/worldgen/biome/elythia_ocean.json
@@ -54,7 +54,8 @@
[
"minecraft:sea_pickle",
"minecraft:warm_ocean_vegetation",
- "minecraft:kelp_warm"
+ "minecraft:kelp_warm",
+ "antarchy:giant_lily_pad_patch"
],
[]
],
diff --git a/common/src/main/resources/data/antarchy/worldgen/biome/elythia_river.json b/common/src/main/resources/data/antarchy/worldgen/biome/elythia_river.json
index 8b8caa79..b31c4bd8 100644
--- a/common/src/main/resources/data/antarchy/worldgen/biome/elythia_river.json
+++ b/common/src/main/resources/data/antarchy/worldgen/biome/elythia_river.json
@@ -55,7 +55,8 @@
[],
[
"antarchy:elythia_meadow_flora",
- "minecraft:patch_sugar_cane"
+ "minecraft:patch_sugar_cane",
+ "antarchy:giant_lily_pad_patch"
],
[]
],
diff --git a/common/src/main/resources/data/antarchy/worldgen/configured_feature/giant_lily_pad_patch.json b/common/src/main/resources/data/antarchy/worldgen/configured_feature/giant_lily_pad_patch.json
new file mode 100644
index 00000000..5188ad45
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/worldgen/configured_feature/giant_lily_pad_patch.json
@@ -0,0 +1,4 @@
+{
+ "type": "antarchy:giant_lily_pad_patch",
+ "config": {}
+}
diff --git a/common/src/main/resources/data/antarchy/worldgen/configured_feature/seashell_patch.json b/common/src/main/resources/data/antarchy/worldgen/configured_feature/seashell_patch.json
new file mode 100644
index 00000000..c9987613
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/worldgen/configured_feature/seashell_patch.json
@@ -0,0 +1,4 @@
+{
+ "type": "antarchy:seashell_patch",
+ "config": {}
+}
diff --git a/common/src/main/resources/data/antarchy/worldgen/placed_feature/giant_lily_pad_patch.json b/common/src/main/resources/data/antarchy/worldgen/placed_feature/giant_lily_pad_patch.json
new file mode 100644
index 00000000..b1b0dd8d
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/worldgen/placed_feature/giant_lily_pad_patch.json
@@ -0,0 +1,9 @@
+{
+ "feature": "antarchy:giant_lily_pad_patch",
+ "placement": [
+ { "type": "minecraft:rarity_filter", "chance": 6 },
+ { "type": "minecraft:in_square" },
+ { "type": "minecraft:heightmap", "heightmap": "MOTION_BLOCKING_NO_LEAVES" },
+ { "type": "minecraft:biome" }
+ ]
+}
diff --git a/common/src/main/resources/data/antarchy/worldgen/placed_feature/seashell_patch.json b/common/src/main/resources/data/antarchy/worldgen/placed_feature/seashell_patch.json
new file mode 100644
index 00000000..d51c19d1
--- /dev/null
+++ b/common/src/main/resources/data/antarchy/worldgen/placed_feature/seashell_patch.json
@@ -0,0 +1,19 @@
+{
+ "feature": "antarchy:seashell_patch",
+ "placement": [
+ {
+ "type": "minecraft:rarity_filter",
+ "chance": 10
+ },
+ {
+ "type": "minecraft:in_square"
+ },
+ {
+ "type": "minecraft:heightmap",
+ "heightmap": "OCEAN_FLOOR_WG"
+ },
+ {
+ "type": "minecraft:biome"
+ }
+ ]
+}
diff --git a/common/src/main/resources/data/minecraft/tags/block/flowers.json b/common/src/main/resources/data/minecraft/tags/block/flowers.json
index 14c5c999..d794cdec 100644
--- a/common/src/main/resources/data/minecraft/tags/block/flowers.json
+++ b/common/src/main/resources/data/minecraft/tags/block/flowers.json
@@ -2,6 +2,7 @@
"replace": false,
"values": [
"antarchy:camellia",
+ "antarchy:lotus",
"antarchy:orange_milkweed",
"antarchy:pink_milkweed",
"antarchy:spider_lily"
diff --git a/common/src/main/resources/data/minecraft/tags/block/small_flowers.json b/common/src/main/resources/data/minecraft/tags/block/small_flowers.json
index b41d7661..ae42e249 100644
--- a/common/src/main/resources/data/minecraft/tags/block/small_flowers.json
+++ b/common/src/main/resources/data/minecraft/tags/block/small_flowers.json
@@ -1,6 +1,7 @@
{
"replace": false,
"values": [
+ "antarchy:lotus",
"antarchy:spider_lily"
]
}
diff --git a/common/src/main/resources/data/minecraft/tags/item/fishes.json b/common/src/main/resources/data/minecraft/tags/item/fishes.json
new file mode 100644
index 00000000..12df0487
--- /dev/null
+++ b/common/src/main/resources/data/minecraft/tags/item/fishes.json
@@ -0,0 +1,6 @@
+{
+ "replace": false,
+ "values": [
+ "antarchy:cheep"
+ ]
+}
diff --git a/common/src/main/resources/data/minecraft/tags/item/flowers.json b/common/src/main/resources/data/minecraft/tags/item/flowers.json
index 14c5c999..d794cdec 100644
--- a/common/src/main/resources/data/minecraft/tags/item/flowers.json
+++ b/common/src/main/resources/data/minecraft/tags/item/flowers.json
@@ -2,6 +2,7 @@
"replace": false,
"values": [
"antarchy:camellia",
+ "antarchy:lotus",
"antarchy:orange_milkweed",
"antarchy:pink_milkweed",
"antarchy:spider_lily"
diff --git a/common/src/main/resources/data/minecraft/tags/item/small_flowers.json b/common/src/main/resources/data/minecraft/tags/item/small_flowers.json
index b41d7661..ae42e249 100644
--- a/common/src/main/resources/data/minecraft/tags/item/small_flowers.json
+++ b/common/src/main/resources/data/minecraft/tags/item/small_flowers.json
@@ -1,6 +1,7 @@
{
"replace": false,
"values": [
+ "antarchy:lotus",
"antarchy:spider_lily"
]
}
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabric.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabric.java
index f3d23fb8..88330f92 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabric.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabric.java
@@ -115,6 +115,14 @@ public final class AntarchyFabric implements ModInitializer {
Registries.PLACED_FEATURE,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "star_coral_patch")
);
+ private static final TagKey HAS_SEASHELL = TagKey.create(
+ Registries.BIOME,
+ ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "has_seashell")
+ );
+ private static final ResourceKey SEASHELL_PATCH = ResourceKey.create(
+ Registries.PLACED_FEATURE,
+ ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "seashell_patch")
+ );
@Override
public void onInitialize() {
AntarchyFabricNetworking.register();
@@ -218,6 +226,11 @@ public final class AntarchyFabric implements ModInitializer {
GenerationStep.Decoration.VEGETAL_DECORATION,
STAR_CORAL_PATCH
);
+ BiomeModifications.addFeature(
+ BiomeSelectors.tag(HAS_SEASHELL),
+ GenerationStep.Decoration.VEGETAL_DECORATION,
+ SEASHELL_PATCH
+ );
BiomeModifications.addSpawn(
BiomeSelectors.tag(APPLE_COW_SPAWN_BIOMES),
net.minecraft.world.entity.MobCategory.CREATURE,
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java
index 480bcd53..dce90ea2 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java
@@ -258,6 +258,7 @@ public final class AntarchyFabricContent {
AntarchyObjects.setOctopusBomb(AntarchyFabricEntities.OCTOPUS_BOMB);
AntarchyObjects.setTentacle(AntarchyFabricEntities.TENTACLE);
AntarchyObjects.setKrakensGraspTrident(AntarchyFabricEntities.KRAKENS_GRASP_TRIDENT);
+ AntarchyObjects.setLotus(() -> AntarchyFabricBlocks.LOTUS.get());
AntarchyObjects.setKrakenTentacle(() -> AntarchyFabricItems.KRAKEN_TENTACLE.get());
AntarchyObjects.setKrakensGrasp(() -> AntarchyFabricItems.KRAKENS_GRASP.get());
AntarchyObjects.setOuranwoodDeer(AntarchyFabricEntities.OURANWOOD_DEER);
@@ -281,7 +282,7 @@ public final class AntarchyFabricContent {
AntarchyObjects.setLumenBlock(() -> AntarchyFabricBlocks.LUMEN_BLOCK.get());
AntarchyObjects.setLumenFroglight(() -> AntarchyFabricBlocks.LUMEN_FROGLIGHT.get());
AntarchyObjects.setPeachLeavesParticle(() -> AntarchyFabricMisc.PEACH_LEAVES_PARTICLE.get());
- // AntarchyObjects.setDorrieInventoryMenu(AntarchyFabricMisc.DORRIE_INVENTORY_MENU);
+ AntarchyObjects.setDorrieInventoryMenu(AntarchyFabricMisc.DORRIE_INVENTORY_MENU);
AntarchyObjects.bind(
AntarchyFabricEntities.EASTER_BUNNY,
AntarchyFabricEntities.FLYING_SQUIRREL,
@@ -306,7 +307,7 @@ public final class AntarchyFabricContent {
(java.util.function.Supplier) AntarchyFabricEntities.BOMBER,
(java.util.function.Supplier) AntarchyFabricEntities.BED_BUG,
AntarchyFabricEntities.CHEEP,
- () -> { throw new IllegalStateException("Dorrie is not part of this update yet."); },
+ AntarchyFabricEntities.DORRIE,
() -> AntarchyFabricBlocks.DUPLICATOR_LOG.get(),
() -> AntarchyFabricBlocks.DUPLICATOR_SAPLING.get(),
() -> AntarchyFabricBlocks.DUCT_TAPE.get(),
@@ -371,10 +372,12 @@ public final class AntarchyFabricContent {
() -> AntarchyFabricBlocks.OURANWOOD_SQUIRREL_NEST.get(),
() -> AntarchyFabricBlocks.BRUTALFLY_COCOON_SPAWNER.get(),
() -> AntarchyFabricBlocks.GIANT_LILY_PAD.get(),
+ () -> AntarchyFabricBlocks.SEASHELL.get(),
() -> AntarchyFabricBlocks.ANT_NEST_BLOCK_ENTITY.get(),
() -> AntarchyFabricBlocks.DREAM_CAMPFIRE_BLOCK_ENTITY.get(),
() -> AntarchyFabricBlocks.WASP_NEST_BLOCK_ENTITY.get(),
() -> AntarchyFabricBlocks.HUSHWEED_BLOCK_ENTITY.get(),
+ () -> AntarchyFabricBlocks.SEASHELL_BLOCK_ENTITY.get(),
() -> AntarchyFabricMisc.STINKY_GAS.get(),
() -> AntarchyFabricMisc.STINKY_FLY.get(),
() -> AntarchyFabricMisc.PEACH_LEAVES_PARTICLE.get(),
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java
index 61b2ff3b..92cfcbe7 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java
@@ -72,6 +72,10 @@ public final class AntarchyFabricClientBootstrap {
(net.minecraft.world.level.block.entity.BlockEntityType) AntarchyFabricBlocks.DREAM_CAMPFIRE_BLOCK_ENTITY.get(),
(BlockEntityRendererProvider) CampfireRenderer::new
);
+ BlockEntityRendererRegistry.register(
+ (net.minecraft.world.level.block.entity.BlockEntityType) AntarchyFabricBlocks.SEASHELL_BLOCK_ENTITY.get(),
+ (BlockEntityRendererProvider) SeashellRenderer::new
+ );
EntityRendererRegistry.register(AntarchyFabricEntities.EASTER_BUNNY.get(), EasterBunnyRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.FLYING_SQUIRREL.get(), FlyingSquirrelRenderer::new);
@@ -100,7 +104,7 @@ public final class AntarchyFabricClientBootstrap {
EntityRendererRegistry.register(AntarchyFabricEntities.KRAKEN.get(), KrakenRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.KRAKEN_PART.get(), MultipartPartRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.TENTACLE.get(), com.craisinlord.antarchy.content.client.renderer.TentacleRenderer::new);
- EntityRendererRegistry.register(AntarchyFabricEntities.KRAKENS_GRASP_TRIDENT.get(), ThrownItemRenderer::new);
+ EntityRendererRegistry.register(AntarchyFabricEntities.KRAKENS_GRASP_TRIDENT.get(), com.craisinlord.antarchy.content.client.renderer.KrakensGraspThrownTridentRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.MISSILE_SQUID.get(), MissileSquidRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.OCTOPUS_BOMB.get(), OctopusBombRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.NIGHTMARE.get(), NightmareRenderer::new);
@@ -113,7 +117,6 @@ public final class AntarchyFabricClientBootstrap {
EntityRendererRegistry.register(AntarchyFabricEntities.GROWTH_RAY_PROJECTILE.get(), SizeRayProjectileRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.LUCID_BOLT.get(), LucidBoltRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.LUCID_PEARL_PROJECTILE.get(), ThrownItemRenderer::new);
- EntityRendererRegistry.register(AntarchyFabricEntities.KRAKENS_GRASP_TRIDENT.get(), ThrownItemRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.HUSH_PROJECTILE.get(), HushProjectileRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.BRUTALFLY_ORB.get(), BrutalflyOrbRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.UPWARD_FALLING_BLOCK.get(), UpwardFallingBlockRenderer::new);
@@ -122,8 +125,7 @@ public final class AntarchyFabricClientBootstrap {
EntityRendererRegistry.register(AntarchyFabricEntities.TORETERROR.get(), ToreterrorRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.WATER_BOMB.get(), WaterBombRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.CHEEP.get(), com.craisinlord.antarchy.content.client.renderer.CheepRenderer::new);
- // Dorrie is not part of this update yet.
- // EntityRendererRegistry.register(AntarchyFabricEntities.DORRIE.get(), com.craisinlord.antarchy.content.client.renderer.DorrieRenderer::new);
+ EntityRendererRegistry.register(AntarchyFabricEntities.DORRIE.get(), com.craisinlord.antarchy.content.client.renderer.DorrieRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.OURANWOOD_DEER.get(), com.craisinlord.antarchy.content.client.renderer.OuranwoodDeerRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.GLIMMER.get(), com.craisinlord.antarchy.content.client.renderer.glimmer.GlimmerRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.ELKA.get(), com.craisinlord.antarchy.content.client.renderer.ElkaRenderer::new);
@@ -252,6 +254,7 @@ public final class AntarchyFabricClientBootstrap {
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricBlocks.PINK_MILKWEED.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricBlocks.CAMELLIA.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricBlocks.SPIDER_LILY.get(), RenderType.cutout());
+ BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricBlocks.LOTUS.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricBlocks.GIANT_LILY_PAD.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricBlocks.HUSHWEED.get(), RenderType.cutout());
BlockRenderLayerMap.INSTANCE.putBlock(AntarchyFabricBlocks.CORNEA_STALK.get(), RenderType.cutout());
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java
index e241c595..2f0dc719 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java
@@ -16,6 +16,7 @@ import com.craisinlord.antarchy.content.block.entity.AntNestBlockEntity;
import com.craisinlord.antarchy.content.block.entity.DreamCampfireBlockEntity;
import com.craisinlord.antarchy.content.block.entity.HushweedBlockEntity;
import com.craisinlord.antarchy.content.block.entity.PotentNyxiteBlockEntity;
+import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
import com.craisinlord.antarchy.content.block.entity.WaspNestBlockEntity;
import com.craisinlord.antarchy.content.fluid.BileLiquidBlock;
import com.craisinlord.antarchy.content.fluid.LumenLiquidBlock;
@@ -353,6 +354,10 @@ public final class AntarchyFabricBlocks {
public static final DeferredBlock GIANT_LILY_PAD = BLOCKS.register("giant_lily_pad",
() -> new GiantLilyPadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.LILY_PAD)));
+ public static final DeferredBlock LOTUS = BLOCKS.register("lotus",
+ () -> new com.craisinlord.antarchy.content.block.LotusBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.SPORE_BLOSSOM)));
+ public static final DeferredBlock SEASHELL = BLOCKS.register("seashell",
+ () -> new SeashellBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.TURTLE_EGG).noOcclusion()));
public static final DeferredBlock OURANWOOD_SIGN = BLOCKS.register("ouranwood_sign",
@@ -1008,6 +1013,11 @@ public final class AntarchyFabricBlocks {
(pos, state) -> new PotentNyxiteBlockEntity(pos, state, AntarchyFabricBlocks::potentNyxiteBlockEntityType),
POTENT_NYXITE.get()
).build(null));
+ public static final DeferredHolder, BlockEntityType> SEASHELL_BLOCK_ENTITY = BLOCK_ENTITY_TYPES.register("seashell",
+ () -> BlockEntityType.Builder.of(
+ SeashellBlockEntity::new,
+ SEASHELL.get()
+ ).build(null));
@@ -1027,6 +1037,10 @@ public final class AntarchyFabricBlocks {
return POTENT_NYXITE_BLOCK_ENTITY.get();
}
+ private static BlockEntityType seashellBlockEntityType() {
+ return SEASHELL_BLOCK_ENTITY.get();
+ }
+
private static Block smallBloodCrystalBudBlock() {
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java
index f1f948e8..8b54c6e4 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java
@@ -598,12 +598,11 @@ public final class AntarchyFabricEntities {
- // Dorrie is not part of this update yet.
- // public static final DeferredHolder, EntityType> DORRIE = ENTITY_TYPES.register("dorrie",
- // () -> EntityType.Builder.of(com.craisinlord.antarchy.content.entity.DorrieEntity::new, MobCategory.CREATURE)
- // .sized(1.6F, 1.4F)
- // .clientTrackingRange(10)
- // .build("dorrie"));
+ public static final DeferredHolder, EntityType> DORRIE = ENTITY_TYPES.register("dorrie",
+ () -> EntityType.Builder.of(com.craisinlord.antarchy.content.entity.DorrieEntity::new, MobCategory.CREATURE)
+ .sized(1.6F, 1.4F)
+ .clientTrackingRange(10)
+ .build("dorrie"));
public static final DeferredHolder, EntityType> OURANWOOD_DEER = ENTITY_TYPES.register("ouranwood_deer",
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntityAttributes.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntityAttributes.java
index 1c82accb..078d9ee0 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntityAttributes.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntityAttributes.java
@@ -307,8 +307,7 @@ public final class AntarchyFabricEntityAttributes {
FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.EMPEROR_SCORPION.get(), EmperorScorpionEntity.createAttributes().build());
FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.TORETERROR.get(), ToreterrorEntity.createAttributes().build());
FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.CHEEP.get(), com.craisinlord.antarchy.content.entity.CheepEntity.createAttributes().build());
- // Dorrie is not part of this update yet.
- // FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.DORRIE.get(), com.craisinlord.antarchy.content.entity.DorrieEntity.createAttributes().build());
+ FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.DORRIE.get(), com.craisinlord.antarchy.content.entity.DorrieEntity.createAttributes().build());
FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.OURANWOOD_DEER.get(), com.craisinlord.antarchy.content.entity.OuranwoodDeerEntity.createAttributes().build());
FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.GLIMMER.get(), com.craisinlord.antarchy.content.entity.glimmer.GlimmerEntity.createAttributes().build());
FabricDefaultAttributeRegistry.register(AntarchyFabricEntities.ELKA.get(), com.craisinlord.antarchy.content.entity.ElkaEntity.createAttributes().build());
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java
index a7e9409d..abacab8e 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java
@@ -403,6 +403,8 @@ public final class AntarchyFabricItems {
public static final DeferredItem GIANT_LILY_PAD_ITEM = ITEMS.register("giant_lily_pad",
() -> new PlaceOnWaterBlockItem(AntarchyFabricBlocks.GIANT_LILY_PAD.get(), new Item.Properties()));
+ public static final DeferredItem SEASHELL_ITEM = ITEMS.registerSimpleBlockItem(AntarchyFabricBlocks.SEASHELL);
+ public static final DeferredItem LOTUS_ITEM = ITEMS.registerSimpleBlockItem(AntarchyFabricBlocks.LOTUS);
public static final DeferredItem OURANWOOD_SIGN_ITEM = ITEMS.register("ouranwood_sign",
@@ -1472,10 +1474,15 @@ public final class AntarchyFabricItems {
public static final DeferredItem CHEEP_SPAWN_EGG = ITEMS.register("cheep_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyFabricEntities.CHEEP, 0xFF00AA, 0x00FF44, new Item.Properties()));
+ public static final DeferredItem- CHEEP_ITEM = ITEMS.register("cheep",
+ () -> new Item(new Item.Properties()
+ .food(new net.minecraft.world.food.FoodProperties.Builder()
+ .nutrition(2)
+ .saturationModifier(0.1F)
+ .build())));
- // Dorrie is not part of this update yet.
- // public static final DeferredItem DORRIE_SPAWN_EGG = ITEMS.register("dorrie_spawn_egg",
- // () -> new DeferredSpawnEggItem(AntarchyFabricEntities.DORRIE, 0x6F8CFF, 0xD2F2FF, new Item.Properties()));
+ public static final DeferredItem DORRIE_SPAWN_EGG = ITEMS.register("dorrie_spawn_egg",
+ () -> new DeferredSpawnEggItem(AntarchyFabricEntities.DORRIE, 0x6F8CFF, 0xD2F2FF, new Item.Properties()));
public static final DeferredItem OURANWOOD_DEER_SPAWN_EGG = ITEMS.register("ouranwood_deer_spawn_egg",
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricMisc.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricMisc.java
index c6b3bf88..eb204364 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricMisc.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricMisc.java
@@ -26,6 +26,7 @@ import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBileCystFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynBileVeinFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynCreepvineFeature;
import com.craisinlord.antarchy.content.worldgen.cavaryn.CavarynWallAmberMossFeature;
+import com.craisinlord.antarchy.content.worldgen.ocean.SeashellFeature;
import com.craisinlord.antarchy.content.worldgen.overworld.CornPatchFeature;
import com.craisinlord.antarchy.content.worldgen.thoraxis.NyxiteSpikeConfiguration;
import com.craisinlord.antarchy.content.worldgen.thoraxis.AntiwaterSpringsConfiguration;
@@ -691,6 +692,8 @@ public final class AntarchyFabricMisc {
public static final DeferredHolder, com.craisinlord.antarchy.content.worldgen.ocean.StarCoralPatchFeature> STAR_CORAL_PATCH = FEATURES.register("star_coral_patch",
() -> new com.craisinlord.antarchy.content.worldgen.ocean.StarCoralPatchFeature(NoneFeatureConfiguration.CODEC));
+ public static final DeferredHolder, SeashellFeature> SEASHELL_PATCH = FEATURES.register("seashell_patch",
+ () -> new SeashellFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder, ElythiaFloraFeature> ELYTHIA_BUTTERFLY_FIELDS_FLORA = FEATURES.register("butterfly_fields_flora",
@@ -748,6 +751,9 @@ public final class AntarchyFabricMisc {
public static final DeferredHolder, LumenLilyPadFeature> LUMEN_LILY_PADS = FEATURES.register("lumen_lily_pads",
() -> new LumenLilyPadFeature(NoneFeatureConfiguration.CODEC));
+ public static final DeferredHolder, com.craisinlord.antarchy.content.worldgen.elythia.GiantLilyPadPatchFeature> GIANT_LILY_PAD_PATCH = FEATURES.register("giant_lily_pad_patch",
+ () -> new com.craisinlord.antarchy.content.worldgen.elythia.GiantLilyPadPatchFeature(NoneFeatureConfiguration.CODEC));
+
public static final DeferredHolder, LumenStreamFeature> LUMEN_STREAM = FEATURES.register("lumen_streams",
() -> new LumenStreamFeature(NoneFeatureConfiguration.CODEC));
diff --git a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricSpawnPlacements.java b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricSpawnPlacements.java
index 9a1c4d32..7a1df6dd 100644
--- a/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricSpawnPlacements.java
+++ b/fabric/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricSpawnPlacements.java
@@ -273,8 +273,7 @@ public final class AntarchyFabricSpawnPlacements {
SpawnPlacements.register(AntarchyFabricEntities.MISSILE_SQUID.get(), SpawnPlacementTypes.IN_WATER, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, MissileSquidEntity::canSpawn);
SpawnPlacements.register(AntarchyFabricEntities.OCTOPUS_BOMB.get(), SpawnPlacementTypes.IN_WATER, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, OctopusBombEntity::canSpawn);
SpawnPlacements.register(AntarchyFabricEntities.CHEEP.get(), SpawnPlacementTypes.IN_WATER, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.AbstractFish::checkSurfaceWaterAnimalSpawnRules);
- // Dorrie is not part of this update yet.
- // SpawnPlacements.register(AntarchyFabricEntities.DORRIE.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules);
+ SpawnPlacements.register(AntarchyFabricEntities.DORRIE.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules);
SpawnPlacements.register(AntarchyFabricEntities.OURANWOOD_DEER.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules);
SpawnPlacements.register(AntarchyFabricEntities.GLIMMER.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, com.craisinlord.antarchy.content.entity.glimmer.GlimmerEntity::checkGlimmerSpawnRules);
SpawnPlacements.register(AntarchyFabricEntities.ELKA.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules);
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java
index 240c61c7..f54a9242 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java
@@ -219,7 +219,7 @@ public class AntarchyNeoforge {
(java.util.function.Supplier) AntarchyNeoforgeEntites.BOMBER,
(java.util.function.Supplier) AntarchyNeoforgeEntites.BED_BUG,
AntarchyNeoforgeEntites.CHEEP,
- () -> { throw new IllegalStateException("Dorrie is not part of this update yet."); },
+ AntarchyNeoforgeEntites.DORRIE,
() -> AntarchyNeoforgeBlocks.DUPLICATOR_LOG.get(),
() -> AntarchyNeoforgeBlocks.DUPLICATOR_SAPLING.get(),
() -> AntarchyNeoforgeBlocks.DUCT_TAPE.get(),
@@ -284,10 +284,12 @@ public class AntarchyNeoforge {
() -> AntarchyNeoforgeBlocks.OURANWOOD_SQUIRREL_NEST.get(),
() -> AntarchyNeoforgeBlocks.BRUTALFLY_COCOON_SPAWNER.get(),
() -> AntarchyNeoforgeBlocks.GIANT_LILY_PAD.get(),
+ () -> AntarchyNeoforgeBlocks.SEASHELL.get(),
() -> AntarchyNeoforgeBlocks.ANT_NEST_BLOCK_ENTITY.get(),
() -> AntarchyNeoforgeBlocks.DREAM_CAMPFIRE_BLOCK_ENTITY.get(),
() -> AntarchyNeoforgeBlocks.WASP_NEST_BLOCK_ENTITY.get(),
() -> AntarchyNeoforgeBlocks.HUSHWEED_BLOCK_ENTITY.get(),
+ () -> AntarchyNeoforgeBlocks.SEASHELL_BLOCK_ENTITY.get(),
() -> AntarchyNeoforgeMisc.STINKY_GAS.get(),
() -> AntarchyNeoforgeMisc.STINKY_FLY.get(),
() -> AntarchyNeoforgeMisc.PEACH_LEAVES_PARTICLE.get(),
@@ -298,6 +300,7 @@ public class AntarchyNeoforge {
AntarchyObjects.setOctopusBomb(AntarchyNeoforgeEntites.OCTOPUS_BOMB);
AntarchyObjects.setTentacle(AntarchyNeoforgeEntites.TENTACLE);
AntarchyObjects.setKrakensGraspTrident(AntarchyNeoforgeEntites.KRAKENS_GRASP_TRIDENT);
+ AntarchyObjects.setLotus(() -> AntarchyNeoforgeBlocks.LOTUS.get());
AntarchyObjects.setKrakenTentacle(() -> AntarchyNeoforgeItems.KRAKEN_TENTACLE.get());
AntarchyObjects.setKrakensGrasp(() -> AntarchyNeoforgeItems.KRAKENS_GRASP.get());
AntarchyObjects.setOuranwoodDeer(AntarchyNeoforgeEntites.OURANWOOD_DEER);
@@ -320,8 +323,7 @@ public class AntarchyNeoforge {
AntarchyObjects.setLumenBlock(() -> AntarchyNeoforgeBlocks.LUMEN_BLOCK.get());
AntarchyObjects.setLumenFroglight(() -> AntarchyNeoforgeBlocks.LUMEN_FROGLIGHT.get());
AntarchyObjects.setPeachLeavesParticle(() -> AntarchyNeoforgeMisc.PEACH_LEAVES_PARTICLE.get());
- // Dorrie is not part of this update yet.
- // AntarchyObjects.setDorrieInventoryMenu(AntarchyNeoforgeMisc.DORRIE_INVENTORY_MENU);
+ AntarchyObjects.setDorrieInventoryMenu(AntarchyNeoforgeMisc.DORRIE_INVENTORY_MENU);
}
private static boolean isModLoaded(String modId) {
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java
index 63396b67..25117d28 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java
@@ -85,6 +85,7 @@ public final class AntarchyNeoForgeClient {
@SubscribeEvent
public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerBlockEntityRenderer(AntarchyNeoforgeBlocks.DREAM_CAMPFIRE_BLOCK_ENTITY.get(), CampfireRenderer::new);
+ event.registerBlockEntityRenderer(AntarchyNeoforgeBlocks.SEASHELL_BLOCK_ENTITY.get(), SeashellRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.EASTER_BUNNY.get(), context -> withParalyzedGeoLayer(new EasterBunnyRenderer(context)));
event.registerEntityRenderer(AntarchyNeoforgeEntites.FLYING_SQUIRREL.get(), context -> withParalyzedGeoLayer(new FlyingSquirrelRenderer(context)));
event.registerEntityRenderer(AntarchyNeoforgeEntites.CATERPILLAR.get(), context -> withParalyzedGeoLayer(new CaterpillarRenderer(context)));
@@ -111,7 +112,7 @@ public final class AntarchyNeoForgeClient {
event.registerEntityRenderer(AntarchyNeoforgeEntites.CLOUD_SHARK.get(), context -> withParalyzedGeoLayer(new CloudSharkRenderer(context)));
event.registerEntityRenderer(AntarchyNeoforgeEntites.KRAKEN.get(), context -> withParalyzedGeoLayer(new KrakenRenderer(context)));
event.registerEntityRenderer(AntarchyNeoforgeEntites.TENTACLE.get(), com.craisinlord.antarchy.content.client.renderer.TentacleRenderer::new);
- event.registerEntityRenderer(AntarchyNeoforgeEntites.KRAKENS_GRASP_TRIDENT.get(), ThrownItemRenderer::new);
+ event.registerEntityRenderer(AntarchyNeoforgeEntites.KRAKENS_GRASP_TRIDENT.get(), com.craisinlord.antarchy.content.client.renderer.KrakensGraspThrownTridentRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.MISSILE_SQUID.get(), context -> withParalyzedGeoLayer(new MissileSquidRenderer(context)));
event.registerEntityRenderer(AntarchyNeoforgeEntites.OCTOPUS_BOMB.get(), context -> withParalyzedGeoLayer(new OctopusBombRenderer(context)));
event.registerEntityRenderer(AntarchyNeoforgeEntites.NIGHTMARE.get(), context -> withParalyzedGeoLayer(new NightmareRenderer(context)));
@@ -124,7 +125,6 @@ public final class AntarchyNeoForgeClient {
event.registerEntityRenderer(AntarchyNeoforgeEntites.GROWTH_RAY_PROJECTILE.get(), SizeRayProjectileRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.LUCID_BOLT.get(), LucidBoltRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.LUCID_PEARL_PROJECTILE.get(), ThrownItemRenderer::new);
- event.registerEntityRenderer(AntarchyNeoforgeEntites.KRAKENS_GRASP_TRIDENT.get(), ThrownItemRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.HUSH_PROJECTILE.get(), HushProjectileRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.BRUTALFLY_ORB.get(), BrutalflyOrbRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.UPWARD_FALLING_BLOCK.get(), com.craisinlord.antarchy.content.client.renderer.UpwardFallingBlockRenderer::new);
@@ -133,8 +133,7 @@ public final class AntarchyNeoForgeClient {
event.registerEntityRenderer(AntarchyNeoforgeEntites.TORETERROR.get(), ToreterrorRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.WATER_BOMB.get(), WaterBombRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.CHEEP.get(), context -> withParalyzedGeoLayer(new com.craisinlord.antarchy.content.client.renderer.CheepRenderer(context)));
- // Dorrie is not part of this update yet.
- // event.registerEntityRenderer(AntarchyNeoforgeEntites.DORRIE.get(), context -> new com.craisinlord.antarchy.content.client.renderer.DorrieRenderer(context));
+ event.registerEntityRenderer(AntarchyNeoforgeEntites.DORRIE.get(), context -> new com.craisinlord.antarchy.content.client.renderer.DorrieRenderer(context));
event.registerEntityRenderer(AntarchyNeoforgeEntites.OURANWOOD_DEER.get(), context -> new com.craisinlord.antarchy.content.client.renderer.OuranwoodDeerRenderer(context));
event.registerEntityRenderer(AntarchyNeoforgeEntites.GLIMMER.get(), context -> withParalyzedGeoLayer(new com.craisinlord.antarchy.content.client.renderer.glimmer.GlimmerRenderer(context)));
event.registerEntityRenderer(AntarchyNeoforgeEntites.ELKA.get(), context -> new com.craisinlord.antarchy.content.client.renderer.ElkaRenderer(context));
@@ -497,6 +496,7 @@ public final class AntarchyNeoForgeClient {
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.PINK_MILKWEED.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.CAMELLIA.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.SPIDER_LILY.get(), RenderType.cutout());
+ ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.LOTUS.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.GIANT_LILY_PAD.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.HUSHWEED.get(), RenderType.cutout());
ItemBlockRenderTypes.setRenderLayer(AntarchyNeoforgeBlocks.CORNEA_STALK.get(), RenderType.cutout());
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java
index 1fbfc3c0..e2799365 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java
@@ -8,6 +8,7 @@ import com.craisinlord.antarchy.content.block.entity.AntNestBlockEntity;
import com.craisinlord.antarchy.content.block.entity.DreamCampfireBlockEntity;
import com.craisinlord.antarchy.content.block.entity.HushweedBlockEntity;
import com.craisinlord.antarchy.content.block.entity.PotentNyxiteBlockEntity;
+import com.craisinlord.antarchy.content.block.entity.SeashellBlockEntity;
import com.craisinlord.antarchy.content.block.entity.WaspNestBlockEntity;
import com.craisinlord.antarchy.content.fluid.BileLiquidBlock;
import com.craisinlord.antarchy.content.fluid.LumenLiquidBlock;
@@ -91,6 +92,10 @@ public final class AntarchyNeoforgeBlocks {
() -> new com.craisinlord.antarchy.content.block.SpiderLilyBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.POPPY)));
public static final DeferredBlock GIANT_LILY_PAD = BLOCKS.register("giant_lily_pad",
() -> new GiantLilyPadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.LILY_PAD)));
+ public static final DeferredBlock LOTUS = BLOCKS.register("lotus",
+ () -> new com.craisinlord.antarchy.content.block.LotusBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.SPORE_BLOSSOM)));
+ public static final DeferredBlock SEASHELL = BLOCKS.register("seashell",
+ () -> new SeashellBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.TURTLE_EGG).noOcclusion()));
public static final DeferredBlock OURANWOOD_SIGN = BLOCKS.register("ouranwood_sign",
() -> new StandingSignBlock(AntarchyWoodTypes.OURANWOOD, BlockBehaviour.Properties.ofFullCopy(Blocks.JUNGLE_SIGN)));
public static final DeferredBlock OURANWOOD_WALL_SIGN = BLOCKS.register("ouranwood_wall_sign",
@@ -446,6 +451,11 @@ public final class AntarchyNeoforgeBlocks {
(pos, state) -> new PotentNyxiteBlockEntity(pos, state, AntarchyNeoforgeItems::potentNyxiteBlockEntityType),
POTENT_NYXITE.get()
).build(null));
+ public static final DeferredHolder, BlockEntityType> SEASHELL_BLOCK_ENTITY = BLOCK_ENTITY_TYPES.register("seashell",
+ () -> BlockEntityType.Builder.of(
+ SeashellBlockEntity::new,
+ SEASHELL.get()
+ ).build(null));
private AntarchyNeoforgeBlocks() {}
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java
index b8fc6296..6245ef58 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeCreativeModeTabs.java
@@ -81,8 +81,7 @@ public class AntarchyNeoforgeCreativeModeTabs {
event.accept(AntarchyNeoforgeItems.BASILISK_SPAWN_EGG.get());
event.accept(AntarchyNeoforgeItems.EMPEROR_SCORPION_SPAWN_EGG.get());
event.accept(AntarchyNeoforgeItems.TORETERROR_SPAWN_EGG.get());
- // Dorrie is not part of this update yet.
- // event.accept(AntarchyNeoforgeItems.DORRIE_SPAWN_EGG.get());
+ event.accept(AntarchyNeoforgeItems.DORRIE_SPAWN_EGG.get());
event.accept(AntarchyNeoforgeItems.OURANWOOD_DEER_SPAWN_EGG.get());
event.accept(AntarchyNeoforgeItems.GLIMMER_SPAWN_EGG.get());
event.accept(AntarchyNeoforgeItems.ELKA_SPAWN_EGG.get());
@@ -100,7 +99,9 @@ public class AntarchyNeoforgeCreativeModeTabs {
event.accept(AntarchyNeoforgeItems.PINK_MILKWEED_ITEM.get());
event.accept(AntarchyNeoforgeItems.CAMELLIA_ITEM.get());
event.accept(AntarchyNeoforgeItems.SPIDER_LILY_ITEM.get());
+ event.accept(AntarchyNeoforgeItems.LOTUS_ITEM.get());
event.accept(AntarchyNeoforgeItems.GIANT_LILY_PAD_ITEM.get());
+ event.accept(AntarchyNeoforgeItems.SEASHELL_ITEM.get());
event.accept(AntarchyNeoforgeItems.HUSHWEED_ITEM.get());
event.accept(AntarchyNeoforgeItems.INFESTED_ROOTED_DIRT_ITEM.get());
event.accept(AntarchyNeoforgeItems.INFESTED_COARSE_DIRT_ITEM.get());
@@ -182,6 +183,7 @@ public class AntarchyNeoforgeCreativeModeTabs {
event.accept(AntarchyNeoforgeItems.COOKED_CORNDOG.get());
event.accept(AntarchyNeoforgeItems.RAW_VENISON.get());
event.accept(AntarchyNeoforgeItems.COOKED_VENISON.get());
+ event.accept(AntarchyNeoforgeItems.CHEEP_ITEM.get());
event.accept(AntarchyNeoforgeItems.ROOT_BEER.get());
event.accept(AntarchyNeoforgeItems.RAINBOW_SUGAR.get());
event.accept(AntarchyNeoforgeItems.BIG_BERTHA_BLADE.get());
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java
index 2d79e54e..5ad7b21a 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java
@@ -315,12 +315,11 @@ public final class AntarchyNeoforgeEntites {
.sized(1.0F, 1.2F)
.clientTrackingRange(8)
.build("cheep"));
- // Dorrie is not part of this update yet.
- // public static final DeferredHolder, EntityType> DORRIE = ENTITY_TYPES.register("dorrie",
- // () -> EntityType.Builder.of(DorrieEntity::new, MobCategory.CREATURE)
- // .sized(1.6F, 1.4F)
- // .clientTrackingRange(10)
- // .build("dorrie"));
+ public static final DeferredHolder, EntityType> DORRIE = ENTITY_TYPES.register("dorrie",
+ () -> EntityType.Builder.of(DorrieEntity::new, MobCategory.CREATURE)
+ .sized(1.6F, 1.4F)
+ .clientTrackingRange(10)
+ .build("dorrie"));
public static final DeferredHolder, EntityType> OURANWOOD_DEER = ENTITY_TYPES.register("ouranwood_deer",
() -> EntityType.Builder.of(OuranwoodDeerEntity::new, MobCategory.CREATURE)
.sized(0.9F, 1.4F)
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntityAttributes.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntityAttributes.java
index 1e84116e..2b7aacb0 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntityAttributes.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntityAttributes.java
@@ -75,8 +75,7 @@ public class AntarchyNeoforgeEntityAttributes {
event.put(AntarchyNeoforgeEntites.MOLEWORM.get(), MolewormEntity.createAttributes().build());
event.put(AntarchyNeoforgeEntites.MOLEVORE.get(), MolevoreEntity.createAttributes().build());
event.put(AntarchyNeoforgeEntites.CHEEP.get(), com.craisinlord.antarchy.content.entity.CheepEntity.createAttributes().build());
- // Dorrie is not part of this update yet.
- // event.put(AntarchyNeoforgeEntites.DORRIE.get(), com.craisinlord.antarchy.content.entity.DorrieEntity.createAttributes().build());
+ event.put(AntarchyNeoforgeEntites.DORRIE.get(), com.craisinlord.antarchy.content.entity.DorrieEntity.createAttributes().build());
event.put(AntarchyNeoforgeEntites.OURANWOOD_DEER.get(), com.craisinlord.antarchy.content.entity.OuranwoodDeerEntity.createAttributes().build());
event.put(AntarchyNeoforgeEntites.GLIMMER.get(), com.craisinlord.antarchy.content.entity.glimmer.GlimmerEntity.createAttributes().build());
event.put(AntarchyNeoforgeEntites.ELKA.get(), ElkaEntity.createAttributes().build());
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java
index a3806df0..f69c38bd 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java
@@ -181,6 +181,8 @@ public final class AntarchyNeoforgeItems {
public static final DeferredItem SPIDER_LILY_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.SPIDER_LILY);
public static final DeferredItem GIANT_LILY_PAD_ITEM = ITEMS.register("giant_lily_pad",
() -> new PlaceOnWaterBlockItem(AntarchyNeoforgeBlocks.GIANT_LILY_PAD.get(), new Item.Properties()));
+ public static final DeferredItem SEASHELL_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.SEASHELL);
+ public static final DeferredItem LOTUS_ITEM = ITEMS.registerSimpleBlockItem(AntarchyNeoforgeBlocks.LOTUS);
public static final DeferredItem OURANWOOD_SIGN_ITEM = ITEMS.register("ouranwood_sign",
() -> new net.minecraft.world.item.SignItem(new Item.Properties().stacksTo(16), AntarchyNeoforgeBlocks.OURANWOOD_SIGN.get(), AntarchyNeoforgeBlocks.OURANWOOD_WALL_SIGN.get()));
public static final DeferredItem OURANWOOD_HANGING_SIGN_ITEM = ITEMS.register("ouranwood_hanging_sign",
@@ -606,9 +608,8 @@ public final class AntarchyNeoforgeItems {
// Spawn eggs
public static final DeferredItem EASTER_BUNNY_SPAWN_EGG = ITEMS.register("easter_bunny_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.EASTER_BUNNY, 0xFFF2B2, 0xFF85B5, new Item.Properties()));
- // Dorrie is not part of this update yet.
- // public static final DeferredItem DORRIE_SPAWN_EGG = ITEMS.register("dorrie_spawn_egg",
- // () -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.DORRIE, 0x6F8CFF, 0xD2F2FF, new Item.Properties()));
+ public static final DeferredItem DORRIE_SPAWN_EGG = ITEMS.register("dorrie_spawn_egg",
+ () -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.DORRIE, 0x6F8CFF, 0xD2F2FF, new Item.Properties()));
public static final DeferredItem OURANWOOD_DEER_SPAWN_EGG = ITEMS.register("ouranwood_deer_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.OURANWOOD_DEER, 0x8A6D4B, 0xE8D9B5, new Item.Properties()));
public static final DeferredItem GLIMMER_SPAWN_EGG = ITEMS.register("glimmer_spawn_egg",
@@ -702,6 +703,12 @@ public final class AntarchyNeoforgeItems {
() -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.TORETERROR, 0x90EE90, 0x5C4033, new Item.Properties().rarity(Rarity.EPIC)));
public static final DeferredItem CHEEP_SPAWN_EGG = ITEMS.register("cheep_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.CHEEP, 0xAA22FF, 0x22FF44, new Item.Properties()));
+ public static final DeferredItem
- CHEEP_ITEM = ITEMS.register("cheep",
+ () -> new Item(new Item.Properties()
+ .food(new net.minecraft.world.food.FoodProperties.Builder()
+ .nutrition(2)
+ .saturationModifier(0.1F)
+ .build())));
public static final DeferredItem
- CREEPING_HORROR_EGG_ITEM = ITEMS.register("creeping_horror_egg",
() -> new MobComingSoonTooltipItem(new Item.Properties().rarity(Rarity.RARE)));
public static final DeferredItem
- LURKING_TERROR_EGG_ITEM = ITEMS.register("lurking_terror_egg",
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeMisc.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeMisc.java
index 1eca9358..9eb57043 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeMisc.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeMisc.java
@@ -12,6 +12,7 @@ import com.craisinlord.antarchy.content.effect.StinkyMobEffect;
import com.craisinlord.antarchy.content.worldgen.ants.BrownAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.RainbowAntNestFeature;
import com.craisinlord.antarchy.content.worldgen.ants.RedAntNestFeature;
+import com.craisinlord.antarchy.content.worldgen.ocean.SeashellFeature;
import com.craisinlord.antarchy.content.worldgen.elythia.*;
import com.craisinlord.antarchy.neoforge.worldgen.CornPatchFeature;
import com.craisinlord.antarchy.neoforge.worldgen.LumenLilyPadFeature;
@@ -241,6 +242,8 @@ public final class AntarchyNeoforgeMisc {
() -> new CornPatchFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder, com.craisinlord.antarchy.content.worldgen.ocean.StarCoralPatchFeature> STAR_CORAL_PATCH = FEATURES.register("star_coral_patch",
() -> new com.craisinlord.antarchy.content.worldgen.ocean.StarCoralPatchFeature(NoneFeatureConfiguration.CODEC));
+ public static final DeferredHolder, SeashellFeature> SEASHELL_PATCH = FEATURES.register("seashell_patch",
+ () -> new SeashellFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder, ElythiaFloraFeature> ELYTHIA_BUTTERFLY_FIELDS_FLORA = FEATURES.register("butterfly_fields_flora",
() -> new ElythiaFloraFeature(NoneFeatureConfiguration.CODEC, ElythiaFloraFeature.Variant.BUTTERFLY_FIELDS));
public static final DeferredHolder, ElythiaSurfaceCoverFeature> ELYTHIA_SURFACE_COVER = FEATURES.register("elythia_surface_cover",
@@ -265,6 +268,8 @@ public final class AntarchyNeoforgeMisc {
() -> new LumenPoolFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder, LumenLilyPadFeature> LUMEN_LILY_PADS = FEATURES.register("lumen_lily_pads",
() -> new LumenLilyPadFeature(NoneFeatureConfiguration.CODEC));
+ public static final DeferredHolder, com.craisinlord.antarchy.content.worldgen.elythia.GiantLilyPadPatchFeature> GIANT_LILY_PAD_PATCH = FEATURES.register("giant_lily_pad_patch",
+ () -> new com.craisinlord.antarchy.content.worldgen.elythia.GiantLilyPadPatchFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder, LumenStreamFeature> LUMEN_STREAM = FEATURES.register("lumen_streams",
() -> new LumenStreamFeature(NoneFeatureConfiguration.CODEC));
public static final DeferredHolder, LumenSpireFeature> LUMEN_SPIRE = FEATURES.register("lumen_spires",
diff --git a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeSpawnPlacements.java b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeSpawnPlacements.java
index 3be87c86..f81cbacc 100644
--- a/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeSpawnPlacements.java
+++ b/neoforge/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeSpawnPlacements.java
@@ -48,8 +48,7 @@ public class AntarchyNeoforgeSpawnPlacements {
event.register(AntarchyNeoforgeEntites.BASILISK.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, BasiliskEntity::canSpawn, RegisterSpawnPlacementsEvent.Operation.OR);
event.register(AntarchyNeoforgeEntites.EMPEROR_SCORPION.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EmperorScorpionEntity::canSpawn, RegisterSpawnPlacementsEvent.Operation.OR);
event.register(AntarchyNeoforgeEntites.CHEEP.get(), SpawnPlacementTypes.IN_WATER, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, AbstractFish::checkSurfaceWaterAnimalSpawnRules, RegisterSpawnPlacementsEvent.Operation.OR);
- // Dorrie is not part of this update yet.
- // event.register(AntarchyNeoforgeEntites.DORRIE.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules, RegisterSpawnPlacementsEvent.Operation.OR);
+ event.register(AntarchyNeoforgeEntites.DORRIE.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules, RegisterSpawnPlacementsEvent.Operation.OR);
event.register(AntarchyNeoforgeEntites.OURANWOOD_DEER.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules, RegisterSpawnPlacementsEvent.Operation.OR);
event.register(AntarchyNeoforgeEntites.GLIMMER.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, com.craisinlord.antarchy.content.entity.glimmer.GlimmerEntity::checkGlimmerSpawnRules, RegisterSpawnPlacementsEvent.Operation.OR);
event.register(AntarchyNeoforgeEntites.ELKA.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, net.minecraft.world.entity.animal.Animal::checkAnimalSpawnRules, RegisterSpawnPlacementsEvent.Operation.OR);
diff --git a/neoforge/src/main/resources/data/antarchy/neoforge/biome_modifier/seashell_in_oceans.json b/neoforge/src/main/resources/data/antarchy/neoforge/biome_modifier/seashell_in_oceans.json
new file mode 100644
index 00000000..f6cd05f7
--- /dev/null
+++ b/neoforge/src/main/resources/data/antarchy/neoforge/biome_modifier/seashell_in_oceans.json
@@ -0,0 +1,6 @@
+{
+ "type": "neoforge:add_features",
+ "biomes": "#antarchy:has_seashell",
+ "features": ["antarchy:seashell_patch"],
+ "step": "vegetal_decoration"
+}