Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multiple snail variants. #6

Open
wants to merge 1 commit into
base: 1.18
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
* @since 1.0.0
*/
public class SnailEntityRenderer extends MobEntityRenderer<SnailEntity, SnailModel> {
public static final Identifier TEXTURE = LovelySnails.id("textures/entity/snail/snail.png");

public SnailEntityRenderer(EntityRendererFactory.Context context) {
super(context, new SnailModel(context.getPart(LovelySnailsClient.SNAIL_MODEL_LAYER)), .5f);
Expand All @@ -48,6 +47,6 @@ public SnailEntityRenderer(EntityRendererFactory.Context context) {

@Override
public Identifier getTexture(SnailEntity entity) {
return TEXTURE;
return entity.getTexture();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,7 @@
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Arm;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Hand;
import net.minecraft.util.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
Expand All @@ -78,6 +75,8 @@
import net.minecraft.world.event.GameEvent;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.function.Predicate;

Expand All @@ -95,6 +94,7 @@ public class SnailEntity extends TameableEntity implements InventoryChangedListe
private static final TrackedData<Byte> SNAIL_FLAGS = DataTracker.registerData(SnailEntity.class, TrackedDataHandlerRegistry.BYTE);
private static final TrackedData<Byte> CHEST_FLAGS = DataTracker.registerData(SnailEntity.class, TrackedDataHandlerRegistry.BYTE);
private static final TrackedData<Integer> CARPET_COLOR = DataTracker.registerData(SnailEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Integer> TRACKED_SNAIL_TYPE = DataTracker.registerData(SnailEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final int SADDLED_FLAG = 0b0000_0001;
private static final int SCARED_FLAG = 0b0000_0010;
private static final int INTERACTION_COOLDOWN_FLAG = 0b0000_0100;
Expand All @@ -104,6 +104,13 @@ public class SnailEntity extends TameableEntity implements InventoryChangedListe

private static final int SATISFACTION_START = -256;

/*
Enum names correspond to the .png filenames for textures
'Special' variants should go at the end of the Enum so that they don't get spawned normally.
*/
public enum SNAIL_TYPE {DEFAULT, CHOCOLATE, HONEY, MACCHIATO, NINJA, OAT, OCHRE, PINK, REDSHELL, SILVER, MOON}
public static final Map<SNAIL_TYPE, Identifier> TEXTURES = new HashMap<>();

private SimpleInventory inventory;
private int satisfaction;
private short interactionCooldown;
Expand All @@ -123,6 +130,17 @@ public static DefaultAttributeContainer.Builder createSnailAttributes() {
.add(EntityAttributes.GENERIC_FOLLOW_RANGE, 48.0);
}

public Identifier getTexture() {
return TEXTURES.getOrDefault(this.getSnailType(), (Identifier)TEXTURES.get(SNAIL_TYPE.DEFAULT));
}
public SNAIL_TYPE getSnailType() {
return SNAIL_TYPE.values()[this.dataTracker.get(TRACKED_SNAIL_TYPE)];
}

public void setSnailType(SNAIL_TYPE type) {
this.dataTracker.set(TRACKED_SNAIL_TYPE, type.ordinal());
}

public static boolean canSpawn(EntityType<? extends AnimalEntity> type, WorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random) {
var spawnBlock = world.getBlockState(pos.down());
return world.getBaseLightLevel(pos, 0) > 8 && spawnBlock.isIn(LovelySnailsRegistry.SNAIL_SPAWN_BLOCKS);
Expand All @@ -133,6 +151,14 @@ public EntityData initialize(ServerWorldAccess world, LocalDifficulty difficulty
@Nullable NbtCompound entityNbt) {
this.setBaby(true);
this.satisfaction = SATISFACTION_START + this.random.nextInt(10);

// 10% chance of special moon snail type if full moon, similar to black cats.
if (world.getMoonSize() > 0.9F && this.random.nextDouble() <= 0.1) {
this.setSnailType(SNAIL_TYPE.MOON);
} else {
this.setSnailType(SNAIL_TYPE.values()[new Random().nextInt(SNAIL_TYPE.values().length - 1)]);
}

return super.initialize(world, difficulty, spawnReason, entityData, entityNbt);
}

Expand Down Expand Up @@ -314,6 +340,7 @@ protected void initDataTracker() {
this.dataTracker.startTracking(SNAIL_FLAGS, (byte) 0);
this.dataTracker.startTracking(CHEST_FLAGS, (byte) 0);
this.dataTracker.startTracking(CARPET_COLOR, -1);
this.dataTracker.startTracking(TRACKED_SNAIL_TYPE, 0);
}

/* Serialization */
Expand All @@ -326,6 +353,7 @@ public void readCustomDataFromNbt(NbtCompound nbt) {
this.setSatisfaction(nbt.contains("satisfaction", NbtElement.INT_TYPE) ?
nbt.getInt("satisfaction") : SATISFACTION_START);
this.setInteractionCooldown(nbt.getShort("interaction_cooldown"));
this.setSnailType(SNAIL_TYPE.values()[nbt.getInt("SnailType")]);

this.readSpecialSlot(nbt, "saddle", SADDLE_SLOT, stack -> stack.isOf(Items.SADDLE));
this.readSpecialSlot(nbt, "decor", CARPET_SLOT,
Expand Down Expand Up @@ -358,6 +386,7 @@ public void writeCustomDataToNbt(NbtCompound nbt) {

nbt.putInt("satisfaction", this.getSatisfaction());
nbt.putShort("interaction_cooldown", this.getInteractionCooldown());
nbt.putInt("SnailType", this.getSnailType().ordinal());

this.writeSpecialSlot(nbt, "saddle", SADDLE_SLOT);
this.writeSpecialSlot(nbt, "decor", CARPET_SLOT);
Expand Down Expand Up @@ -446,9 +475,9 @@ public void openInventory(PlayerEntity player) {

public void openEnderChestInventory(PlayerEntity player) {
if (!this.world.isClient() && (!this.hasPassengers() || this.hasPassenger(player)) && this.isTamed()) {
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((syncId, playerInventory, playerEntity) -> {
return GenericContainerScreenHandler.createGeneric9x3(syncId, playerInventory, player.getEnderChestInventory());
}, new TranslatableText("container.enderchest")));
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((syncId, playerInventory, playerEntity) ->
GenericContainerScreenHandler.createGeneric9x3(syncId, playerInventory, player.getEnderChestInventory()),
new TranslatableText("container.enderchest")));
}
}

Expand Down Expand Up @@ -822,6 +851,15 @@ public PassiveEntity createChild(ServerWorld world, PassiveEntity otherParent) {
}
}

/*
TODO: Expand genetics / breeding mechanics for selecting snail variant.
This currently just randomly picks one of the parent types.
*/
if (otherParent instanceof SnailEntity) {
SNAIL_TYPE type = this.random.nextBoolean() ? this.getSnailType() : ((SnailEntity)otherParent).getSnailType();
assert child != null;
child.setSnailType(type);
}
return child;
}

Expand Down Expand Up @@ -857,4 +895,11 @@ public ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity pl
return new SnailScreenHandler(syncId, inv, snailInv, this.snail(), SnailScreenHandler.getOpeningStoragePage(snailInv));
}
}

static {
/* Turn Enum names into texture locations for the corresponding snail type */
for (var type : SNAIL_TYPE.values()) {
TEXTURES.put(type, LovelySnails.id("textures/entity/snail/" + type.name().toLowerCase() + ".png"));
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.