diff --git a/CHANGELOG.md b/CHANGELOG.md index bb0d4b3674..5be3b25c09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -144,7 +144,7 @@ hi - Added the Penguin. - Penguins spawn in Snowy Beaches and Frozen Oceans. - Will dive underwater to hunt for Squid. - - Can be bred with an Ink Sac or Glow Ink Sac, laying an egg after afterward. + - Can be bred with an Ink Sac or Glow Ink Sac, laying an egg afterward. - Chases Boats controlled by players, granting them a temporary speed boost. - Will occasionally "call" out for other Penguins, grouping together for a short time. - The Penguin will spawn in any biomes within the `wilderwild:entity/spawn/penguin` biome tag. diff --git a/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/PenguinRenderer.java b/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/PenguinRenderer.java index 59dd1ad816..f6ced08a3c 100644 --- a/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/PenguinRenderer.java +++ b/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/PenguinRenderer.java @@ -31,6 +31,7 @@ public class PenguinRenderer extends AgeableMobRenderer> { private static final ResourceLocation TEXTURE = WWConstants.id("textures/entity/penguin/penguin.png"); + private static final ResourceLocation LINUX = WWConstants.id("textures/entity/penguin/linux.png"); public PenguinRenderer(EntityRendererProvider.Context context) { super( @@ -53,14 +54,15 @@ public void extractRenderState(Penguin penguin, PenguinRenderState renderState, renderState.swimAmount = penguin.getSwimAmount(partialTick); renderState.wadeProgress = penguin.getWadeProgress(partialTick); renderState.slideProgress = penguin.getSlideProgress(partialTick); + renderState.isLinux = penguin.isLinux(); renderState.layDownAnimationState = penguin.layDownAnimationState; renderState.standUpAnimationState = penguin.standUpAnimationState; renderState.callAnimationState = penguin.callAnimationState; } @Override - public @NotNull ResourceLocation getTextureLocation(PenguinRenderState livingEntityRenderState) { - return TEXTURE; + public @NotNull ResourceLocation getTextureLocation(@NotNull PenguinRenderState livingEntityRenderState) { + return livingEntityRenderState.isLinux ? LINUX : TEXTURE; } } diff --git a/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/state/PenguinRenderState.java b/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/state/PenguinRenderState.java index e8bb54a1a4..89e29fbe93 100644 --- a/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/state/PenguinRenderState.java +++ b/src/main/java/net/frozenblock/wilderwild/client/renderer/entity/state/PenguinRenderState.java @@ -29,6 +29,7 @@ public class PenguinRenderState extends LivingEntityRenderState { public float swimAmount; public float wadeProgress; public float slideProgress; + public boolean isLinux; public AnimationState layDownAnimationState = new AnimationState(); public AnimationState standUpAnimationState = new AnimationState(); public AnimationState callAnimationState = new AnimationState(); diff --git a/src/main/java/net/frozenblock/wilderwild/config/WWWorldgenConfig.java b/src/main/java/net/frozenblock/wilderwild/config/WWWorldgenConfig.java index 741d73b031..dd57478fe4 100644 --- a/src/main/java/net/frozenblock/wilderwild/config/WWWorldgenConfig.java +++ b/src/main/java/net/frozenblock/wilderwild/config/WWWorldgenConfig.java @@ -170,6 +170,9 @@ public static class BiomePlacement { @EntrySyncData("modifyStonyShorePlacement") public boolean modifyStonyShorePlacement = true; + + @EntrySyncData("modifyAutumnalPlainsPlacement") + public boolean modifyAutumnalPlainsPlacement = false; } public static class BiomeGeneration { diff --git a/src/main/java/net/frozenblock/wilderwild/config/gui/WWWorldgenConfigGui.java b/src/main/java/net/frozenblock/wilderwild/config/gui/WWWorldgenConfigGui.java index 09e9bbd7e4..13aed98464 100644 --- a/src/main/java/net/frozenblock/wilderwild/config/gui/WWWorldgenConfigGui.java +++ b/src/main/java/net/frozenblock/wilderwild/config/gui/WWWorldgenConfigGui.java @@ -20,6 +20,7 @@ import me.shedaniel.clothconfig2.api.ConfigCategory; import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; +import me.shedaniel.clothconfig2.api.Requirement; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.frozenblock.lib.config.api.instance.Config; @@ -460,6 +461,19 @@ public static void setupEntries(@NotNull ConfigCategory category, @NotNull Confi "modifyStonyShorePlacement", configInstance ); + var modifyAutumnalPlainsPlacement = FrozenClothConfig.syncedEntry( + entryBuilder.startBooleanToggle(text("modify_autumnal_plains_placement"), modifiedBiomePlacement.modifyAutumnalPlainsPlacement) + .setDefaultValue(defaultConfig.biomePlacement.modifyAutumnalPlainsPlacement) + .setSaveConsumer(newValue -> biomePlacement.modifyAutumnalPlainsPlacement = newValue) + .setYesNoTextSupplier(bool -> text("biome_placement.autumnal_plains." + bool)) + .setTooltip(tooltip("modify_autumnal_plains_placement")) + .setDisplayRequirement(Requirement.isTrue(() -> WWWorldgenConfig.get().biomeGeneration.generateAutumnalPlains)) + .requireRestart() + .build(), + biomePlacement.getClass(), + "modifyAutumnalPlainsPlacement", + configInstance + ); var swamp = FrozenClothConfig.syncedEntry( entryBuilder.startBooleanToggle(text("modify_swamp_placement"), modifiedBiomePlacement.modifySwampPlacement) .setDefaultValue(defaultConfig.biomePlacement.modifySwampPlacement) @@ -488,7 +502,7 @@ public static void setupEntries(@NotNull ConfigCategory category, @NotNull Confi var biomePlacementCategory = FrozenClothConfig.createSubCategory(entryBuilder, category, text("biome_placement"), false, tooltip("biome_placement"), - cherryGrove, jungle, mangroveSwamp, stonyShore, swamp, windsweptSavanna + cherryGrove, jungle, mangroveSwamp, stonyShore, swamp, windsweptSavanna, modifyAutumnalPlainsPlacement ); var fallenTrees = category.addEntry( diff --git a/src/main/java/net/frozenblock/wilderwild/entity/Penguin.java b/src/main/java/net/frozenblock/wilderwild/entity/Penguin.java index fc6d0448d9..e10cb18495 100644 --- a/src/main/java/net/frozenblock/wilderwild/entity/Penguin.java +++ b/src/main/java/net/frozenblock/wilderwild/entity/Penguin.java @@ -18,14 +18,17 @@ package net.frozenblock.wilderwild.entity; +import com.google.common.collect.ImmutableList; import com.mojang.serialization.Dynamic; import java.util.Arrays; +import java.util.List; import net.frozenblock.wilderwild.config.WWEntityConfig; import net.frozenblock.wilderwild.entity.ai.penguin.PenguinAi; import net.frozenblock.wilderwild.registry.WWEntityTypes; import net.frozenblock.wilderwild.registry.WWSounds; import net.frozenblock.wilderwild.tag.WWBlockTags; import net.frozenblock.wilderwild.tag.WWItemTags; +import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.game.DebugPackets; @@ -68,6 +71,7 @@ import org.jetbrains.annotations.Nullable; public class Penguin extends Animal { + private static final List VALID_LINUX_NAMES = ImmutableList.of("Linux", "Tux", "Treetrain", "Treetrain1"); public static final double BOAT_BOOST_SPEED = 1.7D; public AnimationState layDownAnimationState = new AnimationState(); public AnimationState standUpAnimationState = new AnimationState(); @@ -274,17 +278,17 @@ public void onSyncedDataUpdated(EntityDataAccessor entityDataAccessor) { @Override protected @Nullable SoundEvent getAmbientSound() { - return WWSounds.ENTITY_PENGUIN_IDLE; + return this.isLinux() ? WWSounds.ENTITY_LINUX_IDLE : WWSounds.ENTITY_PENGUIN_IDLE; } @Override protected @Nullable SoundEvent getHurtSound(DamageSource damageSource) { - return WWSounds.ENTITY_PENGUIN_HURT; + return this.isLinux() ? WWSounds.ENTITY_LINUX_HURT : WWSounds.ENTITY_PENGUIN_HURT; } @Override protected @Nullable SoundEvent getDeathSound() { - return WWSounds.ENTITY_PENGUIN_DEATH; + return this.isLinux() ? WWSounds.ENTITY_LINUX_DEATH : WWSounds.ENTITY_PENGUIN_DEATH; } @Override @@ -302,7 +306,7 @@ protected float nextStep() { @Override protected void playStepSound(BlockPos blockPos, BlockState blockState) { if (!this.isSliding()) { - this.playSound(WWSounds.ENTITY_PENGUIN_STEP, 0.1F, 1F); + this.playSound(this.isLinux() ? WWSounds.ENTITY_LINUX_STEP : WWSounds.ENTITY_PENGUIN_STEP, 0.1F, 1F); } else { super.playStepSound(blockPos, blockState); } @@ -339,4 +343,9 @@ public void readAdditionalSaveData(CompoundTag compoundTag) { this.setPose(Pose.valueOf(compoundTag.getString("EntityPose"))); } } + + public boolean isLinux() { + String string = ChatFormatting.stripFormatting(this.getName().getString()); + return VALID_LINUX_NAMES.stream().anyMatch(string::equalsIgnoreCase); + } } diff --git a/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinCall.java b/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinCall.java index 77ec37b903..68afe46234 100644 --- a/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinCall.java +++ b/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinCall.java @@ -55,7 +55,7 @@ protected boolean canStillUse(@NotNull ServerLevel level, @NotNull E penguin, lo protected void start(@NotNull ServerLevel level, @NotNull E penguin, long gameTime) { penguin.stopInPlace(); penguin.setPose(Pose.ROARING); - penguin.playSound(WWSounds.ENTITY_PENGUIN_CALL, 1.2F, 0.9F + penguin.getRandom().nextFloat() * 0.2F); + penguin.playSound(penguin.isLinux() ? WWSounds.ENTITY_LINUX_CALL : WWSounds.ENTITY_PENGUIN_CALL, 1.2F, 0.9F + penguin.getRandom().nextFloat() * 0.2F); penguin.getBrain().setMemory(WWMemoryModuleTypes.CALLING, Unit.INSTANCE); PenguinAi.addCallerMemoryToNearbyPenguins(penguin); diff --git a/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinLayEgg.java b/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinLayEgg.java index a04cbebb26..8fe25e2f43 100644 --- a/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinLayEgg.java +++ b/src/main/java/net/frozenblock/wilderwild/entity/ai/penguin/PenguinLayEgg.java @@ -50,7 +50,7 @@ private static boolean attemptPlace(Penguin entity, @NotNull Level level, Block BlockState placementState = block.defaultBlockState(); level.setBlock(placePos, placementState, Block.UPDATE_ALL); level.gameEvent(GameEvent.BLOCK_PLACE, placePos, GameEvent.Context.of(entity, placementState)); - level.playSound(null, entity, WWSounds.ENTITY_PENGUIN_LAY_EGG, SoundSource.BLOCKS, 1F, 1F); + level.playSound(null, entity, entity.isLinux() ? WWSounds.ENTITY_LINUX_LAY_EGG : WWSounds.ENTITY_PENGUIN_LAY_EGG, SoundSource.BLOCKS, 1F, 1F); return true; } return false; diff --git a/src/main/java/net/frozenblock/wilderwild/registry/WWSounds.java b/src/main/java/net/frozenblock/wilderwild/registry/WWSounds.java index f13abfcf89..d86257d8ba 100644 --- a/src/main/java/net/frozenblock/wilderwild/registry/WWSounds.java +++ b/src/main/java/net/frozenblock/wilderwild/registry/WWSounds.java @@ -303,6 +303,12 @@ public final class WWSounds { public static final SoundEvent ENTITY_PENGUIN_DEATH = register("entity.penguin.death"); public static final SoundEvent ENTITY_PENGUIN_LAY_EGG = register("entity.penguin.lay_egg"); public static final SoundEvent ENTITY_PENGUIN_STEP = register("entity.penguin.step"); + public static final SoundEvent ENTITY_LINUX_IDLE = register("entity.penguin.linux.idle"); + public static final SoundEvent ENTITY_LINUX_CALL = register("entity.penguin.linux.call"); + public static final SoundEvent ENTITY_LINUX_HURT = register("entity.penguin.linux.hurt"); + public static final SoundEvent ENTITY_LINUX_DEATH = register("entity.penguin.linux.death"); + public static final SoundEvent ENTITY_LINUX_LAY_EGG = register("entity.penguin.linux.lay_egg"); + public static final SoundEvent ENTITY_LINUX_STEP = register("entity.penguin.linux.step"); public static final SoundEvent ENTITY_SCORCHED_AMBIENT = register("entity.scorched.ambient"); public static final SoundEvent ENTITY_SCORCHED_HURT = register("entity.scorched.hurt"); public static final SoundEvent ENTITY_SCORCHED_DEATH = register("entity.scorched.death"); diff --git a/src/main/java/net/frozenblock/wilderwild/worldgen/biome/AutumnalPlains.java b/src/main/java/net/frozenblock/wilderwild/worldgen/biome/AutumnalPlains.java index 7f1a1d296b..b49515581b 100644 --- a/src/main/java/net/frozenblock/wilderwild/worldgen/biome/AutumnalPlains.java +++ b/src/main/java/net/frozenblock/wilderwild/worldgen/biome/AutumnalPlains.java @@ -20,11 +20,13 @@ import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Pair; +import java.util.List; import java.util.function.Consumer; import net.frozenblock.lib.worldgen.biome.api.FrozenBiome; import net.frozenblock.lib.worldgen.biome.api.FrozenGrassColorModifiers; import net.frozenblock.lib.worldgen.biome.api.parameters.Continentalness; import net.frozenblock.lib.worldgen.biome.api.parameters.Erosion; +import net.frozenblock.lib.worldgen.biome.api.parameters.FrozenBiomeParameters; import net.frozenblock.lib.worldgen.biome.api.parameters.OverworldBiomeBuilderParameters; import net.frozenblock.lib.worldgen.biome.api.parameters.Weirdness; import net.frozenblock.wilderwild.WWConstants; @@ -74,6 +76,12 @@ public final class AutumnalPlains extends FrozenBiome { public static final Climate.Parameter EROSION_C = Climate.Parameter.span(-0.375F, 0.450F); public static final Climate.Parameter CONTINENTALNESS_C = Climate.Parameter.span(0.030F, 0.800F); + // SNOWY SLOPES TRANSITION + public static final Climate.Parameter WEIRDNESS_SLOPE_A = Climate.Parameter.span(Weirdness.MID_SLICE_NORMAL_ASCENDING, Weirdness.HIGH_SLICE_NORMAL_ASCENDING); + public static final Climate.Parameter WEIRDNESS_SLOPE_B = Climate.Parameter.span(Weirdness.HIGH_SLICE_NORMAL_DESCENDING, Weirdness.MID_SLICE_NORMAL_DESCENDING); + public static final Climate.Parameter WEIRDNESS_SLOPE_C = Climate.Parameter.span(Weirdness.MID_SLICE_VARIANT_ASCENDING, Weirdness.HIGH_SLICE_VARIANT_ASCENDING); + public static final Climate.Parameter WEIRDNESS_SLOPE_D = Climate.Parameter.span(Weirdness.HIGH_SLICE_VARIANT_DESCENDING, Weirdness.MID_SLICE_VARIANT_DESCENDING); + // WITH MAPLE FOREST public static final Climate.Parameter TEMPERATURE_MAPLE = Climate.Parameter.span(-0.495F, -0.255F); public static final Climate.Parameter HUMIDITY_MAPLE = Climate.Parameter.span(-1F, -0.2F); @@ -277,6 +285,54 @@ public void injectToOverworld(Consumer plainsSnowySlopesBorders = FrozenBiomeParameters.findBorderParameters( + OverworldBiomeBuilderParameters.points(Biomes.PLAINS), + OverworldBiomeBuilderParameters.points(Biomes.SNOWY_SLOPES), + 0.15F + ); + + plainsSnowySlopesBorders.forEach(parameterPoint -> { + this.addSurfaceBiome( + parameters, + parameterPoint.temperature(), + parameterPoint.humidity(), + parameterPoint.continentalness(), + parameterPoint.erosion(), + WEIRDNESS_SLOPE_A, + parameterPoint.offset() + ); + this.addSurfaceBiome( + parameters, + parameterPoint.temperature(), + parameterPoint.humidity(), + parameterPoint.continentalness(), + parameterPoint.erosion(), + WEIRDNESS_SLOPE_B, + parameterPoint.offset() + ); + this.addSurfaceBiome( + parameters, + parameterPoint.temperature(), + parameterPoint.humidity(), + parameterPoint.continentalness(), + parameterPoint.erosion(), + WEIRDNESS_SLOPE_C, + parameterPoint.offset() + ); + this.addSurfaceBiome( + parameters, + parameterPoint.temperature(), + parameterPoint.humidity(), + parameterPoint.continentalness(), + parameterPoint.erosion(), + WEIRDNESS_SLOPE_D, + parameterPoint.offset() + ); + }); + } + if (WWWorldgenConfig.get().biomeGeneration.generateMapleForest) { this.addSurfaceBiome( parameters, diff --git a/src/main/resources/assets/wilderwild/lang/en_us.json b/src/main/resources/assets/wilderwild/lang/en_us.json index 5e89d84d52..6a437f7b40 100644 --- a/src/main/resources/assets/wilderwild/lang/en_us.json +++ b/src/main/resources/assets/wilderwild/lang/en_us.json @@ -861,8 +861,12 @@ "tooltip.wilderwild.modify_cherry_grove_placement": "Whether Cherry Groves should use Wilder Wild's or Vanilla's placement.\nWilder Wild's placement allows Cherry Groves to also generate near Rivers.", "option.wilderwild.modify_stony_shore_placement": "Stony Shore Placement", "tooltip.wilderwild.modify_stony_shore_placement": "Whether Stony Shores should use Wilder Wild's or Vanilla's placement.\nWilder Wild's placement replaces Beaches with Stony Shores when near Taigas.", + "option.wilderwild.modify_autumnal_plains_placement": "Autumnal Plains Placement", + "tooltip.wilderwild.modify_autumnal_plains_placement": "Whether Autumnal Plains should use default placement, or also be generated between Plains and Snowy Slopes.", "option.wilderwild.biome_placement.false": "§cVanilla", "option.wilderwild.biome_placement.true": "§aNew", + "option.wilderwild.biome_placement.autumnal_plains.false": "§cDefault", + "option.wilderwild.biome_placement.autumnal_plains.true": "§aInclude On Slopes", "option.wilderwild.biome_generation": "Biome Generation", "tooltip.wilderwild.biome_generation": "Contains options that dictate whether Wilder Wild's biomes should generate or not.", diff --git a/src/main/resources/assets/wilderwild/sounds.json b/src/main/resources/assets/wilderwild/sounds.json index 07a921e937..204e17d982 100644 --- a/src/main/resources/assets/wilderwild/sounds.json +++ b/src/main/resources/assets/wilderwild/sounds.json @@ -2394,6 +2394,15 @@ ], "subtitle": "subtitles.entity.penguin.lay_egg" }, + "entity.penguin.linux.lay_egg": { + "sounds": [ + "wilderwild:mob/penguin/linux/out1", + "wilderwild:mob/penguin/linux/out2", + "wilderwild:mob/penguin/linux/out3", + "wilderwild:mob/penguin/linux/out4" + ], + "subtitle": "subtitles.entity.penguin.linux.lay_egg" + }, "entity.firefly.hide": { "sounds": [ { @@ -2764,6 +2773,51 @@ ], "subtitle": "subtitles.block.generic.footsteps" }, + "entity.penguin.linux.hurt": { + "sounds": [ + "wilderwild:mob/penguin/hurt1", + "wilderwild:mob/penguin/hurt2", + "wilderwild:mob/penguin/hurt3", + "wilderwild:mob/penguin/hurt4" + ], + "subtitle": "subtitles.entity.penguin.linux.hurt" + }, + "entity.penguin.linux.death": { + "sounds": [ + "wilderwild:mob/penguin/hurt1", + "wilderwild:mob/penguin/hurt2", + "wilderwild:mob/penguin/hurt3", + "wilderwild:mob/penguin/hurt4" + ], + "subtitle": "subtitles.entity.penguin.linux.death" + }, + "entity.penguin.linux.idle": { + "sounds": [ + "wilderwild:mob/penguin/linux/idle1" + ], + "subtitle": "subtitles.entity.penguin.linux.idle" + }, + "entity.penguin.linux.call": { + "sounds": [ + "wilderwild:mob/penguin/call1", + "wilderwild:mob/penguin/call2", + "wilderwild:mob/penguin/call3", + "wilderwild:mob/penguin/call4", + "wilderwild:mob/penguin/call5", + "wilderwild:mob/penguin/call6", + "wilderwild:mob/penguin/call7" + ], + "subtitle": "subtitles.entity.penguin.linux.call" + }, + "entity.penguin.linux.step": { + "sounds": [ + "wilderwild:mob/penguin/step1", + "wilderwild:mob/penguin/step2", + "wilderwild:mob/penguin/step3", + "wilderwild:mob/penguin/step4" + ], + "subtitle": "subtitles.block.generic.footsteps" + }, "entity.scorched.ambient": { "sounds": [ "wilderwild:mob/scorched/say1", diff --git a/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/idle1.ogg b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/idle1.ogg new file mode 100644 index 0000000000..b1a43dec53 Binary files /dev/null and b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/idle1.ogg differ diff --git a/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out1.ogg b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out1.ogg new file mode 100644 index 0000000000..e9f4f5aafc Binary files /dev/null and b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out1.ogg differ diff --git a/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out2.ogg b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out2.ogg new file mode 100644 index 0000000000..41064f1501 Binary files /dev/null and b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out2.ogg differ diff --git a/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out3.ogg b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out3.ogg new file mode 100644 index 0000000000..a5004fee89 Binary files /dev/null and b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out3.ogg differ diff --git a/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out4.ogg b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out4.ogg new file mode 100644 index 0000000000..b612e7733d Binary files /dev/null and b/src/main/resources/assets/wilderwild/sounds/mob/penguin/linux/out4.ogg differ diff --git a/src/main/resources/assets/wilderwild/textures/entity/penguin/linux.png b/src/main/resources/assets/wilderwild/textures/entity/penguin/linux.png new file mode 100644 index 0000000000..ee78148202 Binary files /dev/null and b/src/main/resources/assets/wilderwild/textures/entity/penguin/linux.png differ