mirror of
https://github.com/TeamMidnightDust/Puddles.git
synced 2025-12-16 20:15:10 +01:00
Puddles 1.0.0
This commit is contained in:
29
src/main/java/eu/midnightdust/puddles/Puddles.java
Normal file
29
src/main/java/eu/midnightdust/puddles/Puddles.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package eu.midnightdust.puddles;
|
||||
|
||||
import eu.midnightdust.puddles.block.PuddleBlock;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
|
||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.GameRules;
|
||||
|
||||
public class Puddles implements ModInitializer {
|
||||
public static final String MOD_ID = "puddles";
|
||||
public static final Block Puddle = new PuddleBlock(Fluids.WATER, FabricBlockSettings.of(Material.WATER));
|
||||
public static GameRules.Key<GameRules.IntRule> PUDDLE_SPAWN_RATE;
|
||||
public static GameRules.Key<GameRules.IntRule> SNOW_STACK_CHANCE;
|
||||
|
||||
public void onInitialize() {
|
||||
PUDDLE_SPAWN_RATE = GameRuleRegistry.register("puddleSpawnRate", GameRules.Category.SPAWNING, GameRuleFactory.createIntRule(1));
|
||||
SNOW_STACK_CHANCE = GameRuleRegistry.register("snowStackChance", GameRules.Category.SPAWNING, GameRuleFactory.createIntRule(1));
|
||||
Registry.register(Registry.BLOCK, new Identifier(MOD_ID,"puddle"), Puddle);
|
||||
Registry.register(Registry.ITEM, new Identifier(MOD_ID,"puddle"), new BlockItem(Puddle, new Item.Settings()));
|
||||
}
|
||||
}
|
||||
33
src/main/java/eu/midnightdust/puddles/PuddlesClient.java
Normal file
33
src/main/java/eu/midnightdust/puddles/PuddlesClient.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package eu.midnightdust.puddles;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
|
||||
import net.fabricmc.fabric.impl.client.rendering.ColorProviderRegistryImpl;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BuiltinBiomes;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static eu.midnightdust.puddles.Puddles.*;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PuddlesClient implements ClientModInitializer {
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
// Colored Puddle Items & Blocks
|
||||
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||
int waterColor;
|
||||
if (client.world != null) {
|
||||
Biome biome = client.world.getBiome(client.player.getBlockPos());
|
||||
waterColor = biome.getWaterColor();
|
||||
} else waterColor = BuiltinBiomes.PLAINS.getWaterColor();
|
||||
|
||||
ColorProviderRegistry.ITEM.register((stack, tintIndex) -> waterColor, Puddles.Puddle);
|
||||
});
|
||||
|
||||
ColorProviderRegistry.BLOCK.register((state, view, pos, tintIndex) -> Objects.requireNonNull(ColorProviderRegistryImpl.BLOCK.get(Blocks.WATER)).getColor(state, view, pos, tintIndex), Puddle);
|
||||
}
|
||||
}
|
||||
166
src/main/java/eu/midnightdust/puddles/block/PuddleBlock.java
Normal file
166
src/main/java/eu/midnightdust/puddles/block/PuddleBlock.java
Normal file
@@ -0,0 +1,166 @@
|
||||
package eu.midnightdust.puddles.block;
|
||||
|
||||
import eu.midnightdust.puddles.Puddles;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.entity.ai.pathing.NavigationType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.*;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.loot.context.LootContext;
|
||||
import net.minecraft.potion.PotionUtil;
|
||||
import net.minecraft.potion.Potions;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.stat.Stats;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.WorldView;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PuddleBlock extends Block {
|
||||
|
||||
protected final FlowableFluid fluid;
|
||||
public static final VoxelShape COLLISION_SHAPE;
|
||||
|
||||
public PuddleBlock(FlowableFluid fluid, AbstractBlock.Settings settings) {
|
||||
super(settings);
|
||||
this.fluid = fluid;
|
||||
}
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
ItemStack itemStack = player.getStackInHand(hand);
|
||||
if (itemStack.isEmpty()) {
|
||||
return ActionResult.PASS;
|
||||
} else {
|
||||
Item item = itemStack.getItem();
|
||||
ItemStack waterBottleStack;
|
||||
if (item == Items.GLASS_BOTTLE) {
|
||||
if (!world.isClient) {
|
||||
if (!player.abilities.creativeMode) {
|
||||
waterBottleStack = PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.WATER);
|
||||
player.incrementStat(Stats.USE_CAULDRON);
|
||||
itemStack.decrement(1);
|
||||
if (itemStack.isEmpty()) {
|
||||
player.setStackInHand(hand, waterBottleStack);
|
||||
} else if (!player.inventory.insertStack(waterBottleStack)) {
|
||||
player.dropItem(waterBottleStack, false);
|
||||
} else if (player instanceof ServerPlayerEntity) {
|
||||
((ServerPlayerEntity)player).refreshScreenHandler(player.playerScreenHandler);
|
||||
}
|
||||
}
|
||||
|
||||
world.playSound(null, pos, SoundEvents.ITEM_BOTTLE_FILL, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||
world.setBlockState(pos, Blocks.AIR.getDefaultState());
|
||||
}
|
||||
return ActionResult.success(world.isClient);
|
||||
}
|
||||
else return ActionResult.FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public boolean hasRandomTicks(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
|
||||
if (!world.isRaining() && random.nextInt(2000) == 0) {
|
||||
world.setBlockState(pos, Blocks.AIR.getDefaultState());
|
||||
}
|
||||
|
||||
this.scheduledTick(state, world, pos, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
return context.isAbove(COLLISION_SHAPE, pos, true) ? COLLISION_SHAPE : VoxelShapes.empty();
|
||||
}
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
return COLLISION_SHAPE;
|
||||
}
|
||||
@Override
|
||||
public VoxelShape getCullingShape(BlockState state, BlockView world, BlockPos pos) {
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public FluidState getFluidState(BlockState state) {
|
||||
return fluid.getFlowing(1,false);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
|
||||
return stateFrom.getFluidState().getFluid().matchesType(this.fluid);
|
||||
}
|
||||
|
||||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.INVISIBLE;
|
||||
}
|
||||
|
||||
public List<ItemStack> getDroppedStacks(BlockState state, LootContext.Builder builder) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
|
||||
if (world.getBlockState(pos) == Blocks.AIR.getDefaultState() || world.getBlockState(pos) == Puddles.Puddle.getDefaultState()) {
|
||||
int i;
|
||||
// Check if there are fluids on the sides or corners of the block above
|
||||
for (i = 2; i < 6; ++i) {
|
||||
BlockPos pos1 = pos.up();
|
||||
BlockPos pos2 = pos1.offset(Direction.byId(i));
|
||||
if (!world.getFluidState(pos1.offset(Direction.byId(i))).isEmpty()) {
|
||||
// When sides of the block above have water don't place the puddle
|
||||
return false;
|
||||
}
|
||||
if (!world.getFluidState(pos2.offset(Direction.byId(i).rotateYClockwise())).isEmpty()) {
|
||||
// When corners of the block above have water don't place the puddle
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Check if there are fluids on the sides or corners of the block below
|
||||
for (i = 2; i < 6; ++i) {
|
||||
BlockPos pos1 = pos.down();
|
||||
BlockPos pos2 = pos1.offset(Direction.byId(i));
|
||||
if (!world.getFluidState(pos1.offset(Direction.byId(i))).isEmpty()) {
|
||||
// When sides of the block below have water don't place the puddle
|
||||
return false;
|
||||
}
|
||||
if (!world.getFluidState(pos2.offset(Direction.byId(i).rotateYClockwise())).isEmpty()) {
|
||||
// When corners of the block below have water don't place the puddle
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return world.getBlockState(pos.down()).isSideSolidFullSquare(world, pos, Direction.UP);
|
||||
}
|
||||
// When there's already another block at the position don't place the puddle
|
||||
else return false;
|
||||
}
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState newState, WorldAccess world, BlockPos pos, BlockPos posFrom) {
|
||||
return !state.canPlaceAt(world, pos) ? Blocks.AIR.getDefaultState() : super.getStateForNeighborUpdate(state, direction, newState, world, pos, posFrom);
|
||||
}
|
||||
|
||||
static {
|
||||
COLLISION_SHAPE = net.minecraft.block.Block.createCuboidShape(0.0D, 0.0D, 0.0D, 16.0D, 0.5D, 16.0D);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package eu.midnightdust.puddles.mixin;
|
||||
|
||||
import eu.midnightdust.puddles.Puddles;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.*;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Mixin(ServerWorld.class)
|
||||
public abstract class MixinServerWorld extends World {
|
||||
protected MixinServerWorld(MutableWorldProperties properties, RegistryKey<World> registryRef, DimensionType dimensionType, Supplier<Profiler> profiler, boolean isClient, boolean debugWorld, long seed) {
|
||||
super(properties, registryRef, dimensionType, profiler, isClient, debugWorld, seed);
|
||||
}
|
||||
|
||||
@Shadow protected abstract BlockPos getSurface(BlockPos pos);
|
||||
|
||||
@Inject(at = @At("TAIL"),method = "tickChunk")
|
||||
public void tickChunk(WorldChunk chunk, int randomTickSpeed, CallbackInfo ci) {
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
boolean bl = this.isRaining();
|
||||
int x = chunkPos.getStartX();
|
||||
int z = chunkPos.getStartZ();
|
||||
Profiler profiler = this.getProfiler();
|
||||
BlockPos pos;
|
||||
|
||||
if (this.getGameRules().getInt(Puddles.PUDDLE_SPAWN_RATE) != 0) {
|
||||
profiler.push("puddles");
|
||||
if (bl && random.nextInt(10000 / this.getGameRules().getInt(Puddles.PUDDLE_SPAWN_RATE)) == 0) {
|
||||
pos = this.getSurface(getRandomPosInChunk(x, 0, z, 15));
|
||||
if (this.hasRain(pos) && getBlockState(pos.down()).isSideSolidFullSquare(this, pos, Direction.UP)) {
|
||||
setBlockState(pos, Puddles.Puddle.getDefaultState());
|
||||
}
|
||||
}
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
if (this.getGameRules().getInt(Puddles.SNOW_STACK_CHANCE) != 0) {
|
||||
profiler.push("extra_snow");
|
||||
if (bl && random.nextInt(10000 / this.getGameRules().getInt(Puddles.SNOW_STACK_CHANCE)) == 0) {
|
||||
pos = this.getSurface(getRandomPosInChunk(x, 0, z, 15));
|
||||
if (this.getBlockState(pos).getBlock() == Blocks.SNOW && getBlockState(pos.down()).isSideSolidFullSquare(this, pos, Direction.UP)) {
|
||||
int layer = getBlockState(pos).get(Properties.LAYERS);
|
||||
setBlockState(pos, Blocks.SNOW.getDefaultState().with(Properties.LAYERS, layer + 1));
|
||||
}
|
||||
}
|
||||
profiler.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "puddles:block/puddle"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
src/main/resources/assets/puddles/icon.png
Normal file
BIN
src/main/resources/assets/puddles/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
3
src/main/resources/assets/puddles/lang/en_us.json
Normal file
3
src/main/resources/assets/puddles/lang/en_us.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"block.puddles.puddle":"Puddle"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"credit": "made by Motschen",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"particle": "block/water_still"
|
||||
}
|
||||
}
|
||||
22
src/main/resources/assets/puddles/models/item/puddle.json
Normal file
22
src/main/resources/assets/puddles/models/item/puddle.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"credit": "made by Motschen",
|
||||
"parent": "block/block",
|
||||
"textures": {
|
||||
"0": "block/water_still",
|
||||
"particle": "block/water_still"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [16, 1, 16],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 16, 1], "texture": "#0", "tintindex": 0},
|
||||
"east": {"uv": [0, 0, 16, 1], "texture": "#0", "tintindex": 0},
|
||||
"south": {"uv": [0, 0, 16, 1], "texture": "#0", "tintindex": 0},
|
||||
"west": {"uv": [0, 0, 16, 1], "texture": "#0", "tintindex": 0},
|
||||
"up": {"uv": [0, 0, 16, 16], "texture": "#0", "tintindex": 0},
|
||||
"down": {"uv": [0, 0, 16, 16], "texture": "#0", "tintindex": 0}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
34
src/main/resources/fabric.mod.json
Normal file
34
src/main/resources/fabric.mod.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "puddles",
|
||||
"version": "${version}",
|
||||
|
||||
"name": "Puddles",
|
||||
"description": "Adds puddles. Compatible with your favorite shaderpacks & mods!",
|
||||
"authors": [
|
||||
"Motschen",
|
||||
"TeamMidnightDust"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://www.midnightdust.eu/",
|
||||
"sources": "https://github.com/TeamMidnightDust/Puddles",
|
||||
"issues": "https://github.com/TeamMidnightDust/Puddles/issues"
|
||||
},
|
||||
|
||||
"license": "MIT",
|
||||
"icon": "assets/puddles/icon.png",
|
||||
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"eu.midnightdust.puddles.Puddles"
|
||||
],
|
||||
"client": [
|
||||
"eu.midnightdust.puddles.PuddlesClient"
|
||||
]
|
||||
},
|
||||
|
||||
"mixins": [
|
||||
"puddles.mixins.json"
|
||||
]
|
||||
}
|
||||
11
src/main/resources/puddles.mixins.json
Normal file
11
src/main/resources/puddles.mixins.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "eu.midnightdust.puddles.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"MixinServerWorld"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user