Puddles 1.0.0

This commit is contained in:
Motschen
2021-03-30 20:13:33 +02:00
parent 1acdc65fd6
commit 0342b5f312
20 changed files with 817 additions and 0 deletions

View 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()));
}
}

View 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);
}
}

View 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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "puddles:block/puddle"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,3 @@
{
"block.puddles.puddle":"Puddle"
}

View File

@@ -0,0 +1,7 @@
{
"credit": "made by Motschen",
"parent": "block/block",
"textures": {
"particle": "block/water_still"
}
}

View 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}
}
}
]
}

View 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"
]
}

View File

@@ -0,0 +1,11 @@
{
"required": true,
"package": "eu.midnightdust.puddles.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"MixinServerWorld"
],
"injectors": {
"defaultRequire": 1
}
}