Skip to content

Commit

Permalink
Bump baseline handler, trapdoor handler, and simple piston handler im…
Browse files Browse the repository at this point in the history
…plemented. Redstone mixins implemented for powering blocks on bump. Implemented Ground Pound. Moved collision-related action transitions to PostMove.
  • Loading branch information
floral-qua-floral committed Nov 14, 2024
1 parent af1a736 commit 6ffeae1
Show file tree
Hide file tree
Showing 27 changed files with 547 additions and 87 deletions.
13 changes: 7 additions & 6 deletions src/main/java/com/floralquafloral/MarioCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ public static void registerMarioCommand() {
.executes(context -> executeBump(context, false, Direction.UP, 4))
.then(makeBumpDirectionFork("up", Direction.UP))
.then(makeBumpDirectionFork("down", Direction.DOWN))
// .then(makeBumpDirectionFork("north", Direction.NORTH))
// .then(makeBumpDirectionFork("south", Direction.SOUTH))
// .then(makeBumpDirectionFork("east", Direction.EAST))
// .then(makeBumpDirectionFork("west", Direction.WEST))
.then(makeBumpDirectionFork("north", Direction.NORTH))
.then(makeBumpDirectionFork("south", Direction.SOUTH))
.then(makeBumpDirectionFork("east", Direction.EAST))
.then(makeBumpDirectionFork("west", Direction.WEST))
)
)
)
Expand Down Expand Up @@ -153,9 +153,10 @@ private static int executeBump(CommandContext<ServerCommandSource> context, bool
BlockPos position = BlockPosArgumentType.getBlockPos(context, "position");

MarioServerData data = (MarioServerData) MarioDataManager.getMarioData(bumper);
BumpManager.bumpResponseCommon(data, data, bumper.getServerWorld(), bumper.getServerWorld().getBlockState(position), position, strength, strength, direction);
BumpManager.bumpBlockServer(data, bumper.getServerWorld(), position, strength, strength, direction, true, true);
// BumpManager.bumpResponseCommon(data, data, bumper.getServerWorld(), bumper.getServerWorld().getBlockState(position), position, strength, strength, direction);

return sendFeedback(context, "Made " + bumper + " bump block " + direction + " with a strength " + strength);
return sendFeedback(context, "Made " + bumper.getName().getString() + " bump block " + direction + " with a strength " + strength);
}
private static LiteralArgumentBuilder<ServerCommandSource> makeBumpDirectionFork(String name, Direction direction) {
return literal(name)
Expand Down
118 changes: 108 additions & 10 deletions src/main/java/com/floralquafloral/bumping/BumpManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,33 @@
import com.floralquafloral.bumping.handlers.BumpingHandler;
import com.floralquafloral.mariodata.MarioClientSideData;
import com.floralquafloral.mariodata.MarioData;
import com.floralquafloral.mariodata.MarioDataManager;
import com.floralquafloral.mariodata.MarioDataPackets;
import com.floralquafloral.mariodata.moveable.MarioMainClientData;
import com.floralquafloral.mariodata.moveable.MarioServerData;
import com.floralquafloral.mariodata.moveable.MarioTravelData;
import com.floralquafloral.registries.RegistryManager;
import com.floralquafloral.util.MarioSFX;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
Expand All @@ -41,10 +53,13 @@ public abstract class BumpManager {
private record BlockBumpingPlan(ClientWorld world, BlockPos pos, BlockState state, Direction direction) {}

public static void registerPackets() {
BumpC2SPayload.register();
BumpC2SPayload.registerReceiver();

BumpS2CPayload.register();
}
public static void registerPacketsClient() {

BumpS2CPayload.registerReceiver();
}

private static BlockPos eyeAdjustmentParticlePos;
Expand Down Expand Up @@ -78,6 +93,21 @@ public static void registerEventListeners() {
assert hitResult != null;
return hitResult.getType() != HitResult.Type.BLOCK || !HIDDEN_BLOCKS.contains(((BlockHitResult) hitResult).getBlockPos());
});

ServerTickEvents.END_SERVER_TICK.register((server) -> {
Set<BaselineBumpingHandler.ForcedSignalSpot> removeSpots = null;
for(BaselineBumpingHandler.ForcedSignalSpot spot : BaselineBumpingHandler.FORCED_SIGNALS_DATA) {
if(spot.delay-- <= 0) {
BaselineBumpingHandler.FORCED_SIGNALS.remove(spot.POSITION);
spot.WORLD.updateNeighbor(spot.POSITION, spot.WORLD.getBlockState(spot.POSITION).getBlock(), spot.POSITION);
if(removeSpots == null) removeSpots = new HashSet<>();
removeSpots.add(spot);
}
}
if(removeSpots != null) for(BaselineBumpingHandler.ForcedSignalSpot spot : removeSpots) {
BaselineBumpingHandler.FORCED_SIGNALS_DATA.remove(spot);
}
});
}

public static void visuallyBumpBlock(ClientWorld world, BlockPos bumpPos, Direction direction) {
Expand Down Expand Up @@ -113,9 +143,10 @@ public static void bumpBlocks(MarioMainClientData data, ClientWorld world, Itera
if(bumpBlockClient(
data, world, lastPos,
baseStrength, modifiedStrength, direction,
false,
blockSoundGroups)) {
bumpCount++;
// Network bump individually? :(
ClientPlayNetworking.send(new BumpC2SPayload(lastPos, direction, baseStrength));
}
}

Expand Down Expand Up @@ -143,13 +174,13 @@ public static void bumpBlocks(MarioMainClientData data, ClientWorld world, Itera
public static boolean bumpBlockClient(
MarioClientSideData data, ClientWorld world, BlockPos pos,
int baseStrength, int modifiedStrength, Direction direction,
@Nullable Set<BlockSoundGroup> soundGroups
boolean force, @Nullable Set<BlockSoundGroup> soundGroups
) {
BlockState blockState = world.getBlockState(pos);

BumpingHandler.BumpLegality result = evaluateBumpLegality(blockState, world, pos, baseStrength, direction);
BumpingHandler.BumpLegality result = evaluateBumpLegality(blockState, world, pos, Math.max(baseStrength, modifiedStrength), direction);

if(result == BumpingHandler.BumpLegality.IGNORE) return false;
if(!force && result == BumpingHandler.BumpLegality.IGNORE) return false;

bumpResponseClients(data, world, blockState, pos, baseStrength, modifiedStrength, direction);
bumpResponseCommon(data, (data instanceof MarioMainClientData mainClientData) ? mainClientData : null,
Expand All @@ -173,13 +204,20 @@ public static boolean bumpBlockClient(
return true;
}

public void bumpBlockServer(
MarioServerData data, ServerWorld world,BlockPos pos,
public static void bumpBlockServer(
MarioServerData data, ServerWorld world, BlockPos pos,
int baseStrength, int modifiedStrength, Direction direction,
boolean networkToMario
boolean force, boolean networkToMario
) {
bumpResponseCommon(data, data, world, world.getBlockState(pos), pos, baseStrength, modifiedStrength, direction);
// MarioPackets.sendPacketToTrackersExclusive(data.getMario(), new );
BlockState blockState = world.getBlockState(pos);
if(!force && evaluateBumpLegality(blockState, world, pos, Math.max(baseStrength, modifiedStrength), direction)
== BumpingHandler.BumpLegality.IGNORE) return;

bumpResponseCommon(data, data, world, blockState, pos, baseStrength, modifiedStrength, direction);

BumpS2CPayload packet = new BumpS2CPayload(data.getMario().getId(), pos, direction, baseStrength);
MarioPackets.sendPacketToTrackersExclusive(data.getMario(), packet);
if(networkToMario) ServerPlayNetworking.send(data.getMario(), packet);
}

public static @NotNull BumpingHandler.BumpLegality evaluateBumpLegality(
Expand Down Expand Up @@ -217,4 +255,64 @@ public static void bumpResponseClients(
}
BASELINE_HANDLER.bumpResponseClients(data, world, state, pos, baseStrength, modifiedStrength, direction);
}

private record BumpC2SPayload(BlockPos pos, Direction direction, int strength) implements CustomPayload {
public static final CustomPayload.Id<BumpC2SPayload> ID = new CustomPayload.Id<>(Identifier.of(MarioQuaMario.MOD_ID, "bump_c2s"));
public static final PacketCodec<RegistryByteBuf, BumpC2SPayload> CODEC = PacketCodec.tuple(
BlockPos.PACKET_CODEC, BumpC2SPayload::pos,
Direction.PACKET_CODEC, BumpC2SPayload::direction,
PacketCodecs.INTEGER, BumpC2SPayload::strength,
BumpC2SPayload::new
);
public static void registerReceiver() {
ServerPlayNetworking.registerGlobalReceiver(ID, (payload, context) -> {
MarioServerData data = (MarioServerData) MarioDataManager.getMarioData(context.player());
bumpBlockServer(
data, context.player().getServerWorld(), payload.pos,
payload.strength,
payload.strength + data.getCharacter().BUMP_STRENGTH_MODIFIER + data.getPowerUp().BUMP_STRENGTH_MODIFIER,
payload.direction,
false, false
);
});
}

@Override public Id<? extends CustomPayload> getId() {
return ID;
}
public static void register() {
PayloadTypeRegistry.playC2S().register(ID, CODEC);
}
}

private record BumpS2CPayload(int player, BlockPos pos, Direction direction, int strength) implements CustomPayload {
public static final CustomPayload.Id<BumpS2CPayload> ID = new CustomPayload.Id<>(Identifier.of(MarioQuaMario.MOD_ID, "bump_s2c"));
public static final PacketCodec<RegistryByteBuf, BumpS2CPayload> CODEC = PacketCodec.tuple(
PacketCodecs.INTEGER, BumpS2CPayload::player,
BlockPos.PACKET_CODEC, BumpS2CPayload::pos,
Direction.PACKET_CODEC, BumpS2CPayload::direction,
PacketCodecs.INTEGER, BumpS2CPayload::strength,
BumpS2CPayload::new
);
public static void registerReceiver() {
ClientPlayNetworking.registerGlobalReceiver(ID, (payload, context) -> {
MarioClientSideData data = (MarioClientSideData) MarioDataManager.getMarioData(context.player());
bumpBlockClient(
data, context.player().clientWorld, payload.pos,
payload.strength,
payload.strength + data.getCharacter().BUMP_STRENGTH_MODIFIER + data.getPowerUp().BUMP_STRENGTH_MODIFIER,
payload.direction,
true,
null
);
});
}

@Override public Id<? extends CustomPayload> getId() {
return ID;
}
public static void register() {
PayloadTypeRegistry.playS2C().register(ID, CODEC);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,96 @@
import net.minecraft.block.BlockState;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.tick.OrderedTick;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static com.floralquafloral.MarioQuaMario.MOD_ID;

public class BaselineBumpingHandler implements BumpingHandler {
public static BlockPos forceRedstoneSignalAtPos;
public static final Set<Pair<BlockPos, Integer>> DELAYED_TICKS = new HashSet<>();

public static final Set<BlockPos> FORCED_SIGNALS = new HashSet<>();
public static final Set<ForcedSignalSpot> FORCED_SIGNALS_DATA = new HashSet<>();

public static class ForcedSignalSpot {
public final BlockPos POSITION;
public final World WORLD;
public int delay;

private ForcedSignalSpot(BlockPos position, World world) {
this.POSITION = position;
this.WORLD = world;
this.delay = 3;
}
}

public static final TagKey<Block> BUMP_REGARDLESS_OF_HARDNESS =
TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "bump_regardless_of_hardness"));
public static final TagKey<Block> UNBUMPABLE = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "unbumpable"));
public static final TagKey<Block> EXTREMELY_EASY_TO_BUMP = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "extremely_easy_to_bump"));

public static final TagKey<Block> DO_NOT_POWER = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "do_not_power_on_bump"));
public static final TagKey<Block> UNBREAKABLE_FROM_BUMPING = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "unbreakable_from_bumping"));
// public static final TagKey<Block> BRICK_BLOCKS = TagKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, "brick_blocks"));

@Override @NotNull
public BumpLegality evaluateBumpLegality(BlockState state, BlockView world, BlockPos pos, int strength, Direction direction) {
if(state.isIn(UNBUMPABLE)) return BumpLegality.IGNORE;
if(state.isIn(BUMP_REGARDLESS_OF_HARDNESS) && strength >= 4) return BumpLegality.BUMP;
if(state.isIn(EXTREMELY_EASY_TO_BUMP) && strength >= 1) return BumpLegality.BUMP;

float hardnessToolless = state.getHardness(world, pos);
if(state.isToolRequired()) hardnessToolless *= 3.33333333333F;
if(state.isTransparent(world, pos) && !state.hasSidedTransparency()) hardnessToolless *= 0.5F;
if(state.isIn(BlockTags.AXE_MINEABLE)) hardnessToolless *= 3.6F;
if(state.getBlock().toString().contains("brick")) hardnessToolless *= 0.5F;

MarioQuaMario.LOGGER.info("BASELINE BUMPING HANDLER:"
+ "\nBlock: " + state.getBlock()
+ "\nHardness: " + state.getHardness(world, pos)
);
if(hardnessToolless == -1) return BumpLegality.IGNORE;

if(strength <= 1) return BumpLegality.IGNORE;
if(strength == 2 && hardnessToolless <= 0.25F) return BumpLegality.SILENT_REACTION;
else if(hardnessToolless <= 2.5F * strength) return BumpLegality.BUMP;

return BumpLegality.IGNORE;
}

@Override
public boolean bumpResponseCommon(MarioData data, @Nullable MarioTravelData travelData, World world, BlockState state, BlockPos pos, int baseStrength, int modifiedStrength, Direction direction) {
float hardnessToolless = state.getHardness(world, pos);
if(state.isToolRequired()) hardnessToolless *= 3.33333333333F;
if(state.isTransparent(world, pos) && !state.hasSidedTransparency()) hardnessToolless *= 0.5F;
if(state.isIn(BlockTags.AXE_MINEABLE)) hardnessToolless *= 3.6F;
if(state.getBlock().toString().contains("brick")) hardnessToolless *= 0.5F;

if(!state.isIn(UNBREAKABLE_FROM_BUMPING) && hardnessToolless != -1) {
if (modifiedStrength >= 4 && hardnessToolless <= 3.5 && world.breakBlock(pos, true, data.getMario()))
return true;

if (modifiedStrength >= 2 && hardnessToolless <= 0.3 && world.breakBlock(pos, true, data.getMario()))
return true;
}

if(!state.isIn(DO_NOT_POWER)) {
FORCED_SIGNALS.add(pos);
FORCED_SIGNALS_DATA.add(new ForcedSignalSpot(pos, world));
world.updateNeighbor(pos, state.getBlock(), pos);
}

return false;
}

Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/floralquafloral/mixin/RedstoneViewMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.floralquafloral.mixin;

import com.floralquafloral.bumping.handlers.BaselineBumpingHandler;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.RedstoneView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(RedstoneView.class)
public interface RedstoneViewMixin {
@Inject(method = "isReceivingRedstonePower", at = @At("HEAD"), cancellable = true)
private void forceReceiveRedstonePower(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
if(BaselineBumpingHandler.FORCED_SIGNALS.contains(pos)) cir.setReturnValue(true);
}

@Inject(method = "getEmittedRedstonePower(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;)I", at = @At("HEAD"), cancellable = true)
private void forceReceiveRedstonePowerBravo(BlockPos pos, Direction direction, CallbackInfoReturnable<Integer> cir) {
if(BaselineBumpingHandler.FORCED_SIGNALS.contains(pos.offset(direction.getOpposite())))
cir.setReturnValue(1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class BumpingRule {
* A strength of 1 represents Mario landing on a block and having no effect on it.
*/
public static final BumpingRule JUMPING = new BumpingRule(4, 1, 0);
public static final BumpingRule FALLING = new BumpingRule(4, 4, 0);
public static final BumpingRule FALLING = new BumpingRule(4, 1, 0);
public static final BumpingRule GROUND_POUND = new BumpingRule(0, 4, 0);
public static final BumpingRule SPIN_JUMPING = new BumpingRule(2, 2, 0);

Expand Down
Loading

0 comments on commit 6ffeae1

Please sign in to comment.