Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
fc8278c
Added ramp tricks and some more sound effects
ToadsworthLP Aug 7, 2025
e6fb8d0
Adjusted boost strength
ToadsworthLP Aug 7, 2025
55d598a
Improved audio mixing
ToadsworthLP Aug 9, 2025
3a8ff88
Improved game feel
ToadsworthLP Aug 9, 2025
2c295ee
Adjusted drift and boost parameters to more closely match MK8DX
ToadsworthLP Aug 10, 2025
4f980ef
Refactored offroad block system
ToadsworthLP Aug 11, 2025
57076fd
Merged rotation smoothing bugfix by mocksonline from PR #129 of the m…
ToadsworthLP Aug 11, 2025
150762a
Added ground particles/sounds and made sound effects more muted while…
ToadsworthLP Aug 11, 2025
e6512b3
Fixed mixin issue on dedicated servers
ToadsworthLP Aug 11, 2025
9ae796b
Added slime bounce sound to launch gel
ToadsworthLP Aug 11, 2025
a0942a2
Slightly lowered volume of block sounds (again)
ToadsworthLP Aug 11, 2025
efebf45
Fixed Quilt maven and tweaked details
ToadsworthLP Aug 13, 2025
e6102d0
Added missing layers to layered offroad blocks
ToadsworthLP Aug 13, 2025
8830f44
Added drift charge sound effect to burnout charge
ToadsworthLP Aug 13, 2025
a95bdc2
Added light block-like offroad marker blocks
ToadsworthLP Aug 13, 2025
844510a
Version bump to 0.5.1
ToadsworthLP Aug 13, 2025
16e37a2
Improved off-road area textures
ToadsworthLP Aug 14, 2025
c32c3a5
Improved off-road area strength scaling
ToadsworthLP Aug 14, 2025
c915a26
Changed off road area default strength to 4
ToadsworthLP Aug 14, 2025
95dba1e
Slightly buffed Gold Engine
ToadsworthLP Jul 7, 2026
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 @@ -28,15 +28,23 @@
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.client.model.Model;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.client.renderer.entity.NoopRenderer;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.BlockItemStateProperties;
import net.minecraft.world.level.GrassColor;
import net.minecraft.world.level.block.LightBlock;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;

public class AutomobilityClient {
Expand Down Expand Up @@ -68,6 +76,15 @@ public static void init() {
)
)
);

ClientLevel.MARKER_PARTICLE_ITEMS = new HashSet<>(ClientLevel.MARKER_PARTICLE_ITEMS);
ClientLevel.MARKER_PARTICLE_ITEMS.add(AutomobilityBlocks.OFF_ROAD_AREA.require().asItem());

//ItemProperties.register(Items.LIGHT, ResourceLocation.withDefaultNamespace("level"), (p_329788_, p_329789_, p_329790_, p_329791_) -> {
// BlockItemStateProperties blockitemstateproperties = p_329788_.getOrDefault(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY);
// Integer integer = blockitemstateproperties.get(LightBlock.LEVEL);
// return integer != null ? (float)integer.intValue() / 16.0F : 1.0F;
//});
}

public static void initBlocks() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public static AutomobileEngine create(boolean empty, float torque, float speed,
));

public static final ResourceKey<AutomobileEngine> GOLD = BOOTSTRAP.register(Automobility.rl("gold"), of(
0.8f, 0.75f,
0.8f, 0.8f,
AutomobilitySounds.GOLD_ENGINE::require,
model(
Automobility.rl("textures/entity/automobile/engine/gold.png"), Automobility.rl("engine/gold"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LightBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.material.MapColor;

import java.util.function.Function;
import java.util.function.Supplier;
Expand All @@ -45,13 +51,12 @@ public enum AutomobilityBlocks {;
public static final Eventual<Block> DASH_PANEL = register("dash_panel", () -> new DashPanelBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.IRON_BLOCK)
.lightLevel(s -> s.getValue(DashPanelBlock.POWERED) ? 0 : 1).emissiveRendering((s, l, p) -> !s.getValue(DashPanelBlock.POWERED)).noCollission()), b -> new DashPanelItem(b, new Item.Properties()), Automobility.TAB);

public static final Eventual<Block> GRASS_OFF_ROAD = register("grass_off_road", () -> new OffRoadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.GRASS_BLOCK).noCollission(), AUtils.colorFromInt(0x406918)), Automobility.TAB);
public static final Eventual<Block> DIRT_OFF_ROAD = register("dirt_off_road", () -> new OffRoadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.DIRT).noCollission(), AUtils.colorFromInt(0x594227)), Automobility.TAB);
public static final Eventual<Block> SAND_OFF_ROAD = register("sand_off_road", () -> new OffRoadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.SAND).noCollission(), AUtils.colorFromInt(0xC2B185)), Automobility.TAB);
public static final Eventual<Block> SNOW_OFF_ROAD = register("snow_off_road", () -> new OffRoadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.SNOW_BLOCK).noCollission(), AUtils.colorFromInt(0xD0E7ED)), Automobility.TAB);

public static final Eventual<Block> GRASS_OFF_ROAD = register("grass_off_road", () -> new LayeredOffroadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.GRASS_BLOCK).noCollission(), AUtils.colorFromInt(0x406918)), Automobility.TAB);
public static final Eventual<Block> DIRT_OFF_ROAD = register("dirt_off_road", () -> new LayeredOffroadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.DIRT).noCollission(), AUtils.colorFromInt(0x594227)), Automobility.TAB);
public static final Eventual<Block> SAND_OFF_ROAD = register("sand_off_road", () -> new LayeredOffroadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.SAND).noCollission(), AUtils.colorFromInt(0xC2B185)), Automobility.TAB);
public static final Eventual<Block> SNOW_OFF_ROAD = register("snow_off_road", () -> new LayeredOffroadBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.SNOW_BLOCK).noCollission(), AUtils.colorFromInt(0xD0E7ED)), Automobility.TAB);
public static final Eventual<Block> LAUNCH_GEL = register("launch_gel", () -> new LaunchGelBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CLAY).strength(0.1f).sound(SoundType.HONEY_BLOCK).noCollission()), Automobility.TAB);

public static final Eventual<Block> OFF_ROAD_AREA = register("off_road_area", () -> new OffroadAreaBlock(BlockBehaviour.Properties.of().replaceable().strength(-1.0F, 3600000.8F).mapColor(waterloggedMapColor(MapColor.NONE)).noLootTable().noOcclusion()), (CreativeTabQueue) null);
public static final Eventual<Block> ALLOW = register("allow", () -> new Block(BlockBehaviour.Properties.ofFullCopy(Blocks.BEDROCK).sound(SoundType.METAL)),
b -> new TooltipBlockItem(b, Component.translatable("tooltip.block.automobility.allow").withStyle(ChatFormatting.AQUA), new Item.Properties()));

Expand All @@ -61,6 +66,10 @@ public enum AutomobilityBlocks {;
Automobility.rl("autopilot_sign"), () -> Platform.get().blockEntity(AutopilotSignBlockEntity::new, AUTOPILOT_SIGN.require()));

public static void init() {
for (int i = 1; i < 9; i++) {
int finalI = i;
Automobility.TAB.queueStack(() -> OffroadAreaBlock.setStrengthOnStack(new ItemStack(OFF_ROAD_AREA.require().asItem()), finalI));
}
}

public static Eventual<Block> register(String name, Supplier<Block> block) {
Expand All @@ -85,4 +94,8 @@ public static Eventual<Block> register(String name, Supplier<Block> block, Funct
public static Eventual<Block> register(String name, Supplier<Block> block, Function<Block, BlockItem> item) {
return register(name, block, item, null);
}

private static Function<BlockState, MapColor> waterloggedMapColor(MapColor unwaterloggedMapColor) {
return (blockState) -> (Boolean)blockState.getValue(BlockStateProperties.WATERLOGGED) ? MapColor.WATER : unwaterloggedMapColor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public static void onCollideWithDashPanel(@Nullable BlockState panelState, Entit
}

if (entity instanceof AutomobileEntity auto) {
auto.boost(0.45f, 50);
auto.boost(0.35f, 50);
} else if (entity.getType().is(AutomobilityEntities.DASH_PANEL_BOOSTABLES)) {
if (entity instanceof LivingEntity living) {
living.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SPEED, 40, 6, true, false, false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void entityInside(BlockState state, Level world, BlockPos pos, Entity ent
super.entityInside(state, world, pos, entity);

if (entity instanceof AutomobileEntity automobile && automobile.automobileOnGround()) {
automobile.boost(0.14f, 7);
automobile.boost(0.13f, 7);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,21 @@
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;

public class OffRoadBlock extends Block {
public static final VoxelShape ONE_LAYER_SHAPE = box(0, 0, 0, 16, 2, 16);
public static final VoxelShape TWO_LAYER_SHAPE = box(0, 0, 0, 16, 4, 16);
public static final VoxelShape THREE_LAYER_SHAPE = box(0, 0, 0, 16, 6, 16);

public static final IntegerProperty LAYERS = IntegerProperty.create("layers", 1, 3);
public class LayeredOffroadBlock extends Block implements OffroadBlock {
public static final int MAX_LAYERS = 8;
public static final IntegerProperty LAYERS = IntegerProperty.create("layers", 1, MAX_LAYERS);

public final Vector3f color;
private static final VoxelShape[] SHAPES_BY_LAYER;

static {
SHAPES_BY_LAYER = new VoxelShape[MAX_LAYERS];
for (int i = 0; i < SHAPES_BY_LAYER.length; i++) {
SHAPES_BY_LAYER[i] = getShapeForLayerCount(i + 1);
}
}

public OffRoadBlock(Properties settings, Vector3f color) {
public LayeredOffroadBlock(Properties settings, Vector3f color) {
super(settings.pushReaction(PushReaction.DESTROY));
registerDefaultState(defaultBlockState().setValue(LAYERS, 1));
this.color = color;
Expand All @@ -35,15 +40,15 @@ public OffRoadBlock(Properties settings, Vector3f color) {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
var state = ctx.getLevel().getBlockState(ctx.getClickedPos());
if (state.is(this) && state.getValue(LAYERS) < 3) {
if (state.is(this) && state.getValue(LAYERS) < MAX_LAYERS) {
return state.setValue(LAYERS, state.getValue(LAYERS) + 1);
}
return super.getStateForPlacement(ctx);
}

@Override
public boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
return state.getValue(LAYERS) < 3 && context.getItemInHand().is(this.asItem());
return state.getValue(LAYERS) < MAX_LAYERS && context.getItemInHand().is(this.asItem());
}

@Override
Expand All @@ -61,16 +66,32 @@ public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {

@Override
public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
return switch (state.getValue(LAYERS)) {
case 2 -> TWO_LAYER_SHAPE;
case 3 -> THREE_LAYER_SHAPE;
default -> ONE_LAYER_SHAPE;
};
int shapeIndex = state.getValue(LAYERS) - 1;
if(shapeIndex >= 0 && shapeIndex < SHAPES_BY_LAYER.length) {
return SHAPES_BY_LAYER[shapeIndex];
} else {
return SHAPES_BY_LAYER[0];
}
}

@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(LAYERS);
}

@Override
public float getSpeedMultiplier(BlockState blockState) {
int layers = blockState.getValue(LayeredOffroadBlock.LAYERS);
return (float) ((-40 * layers) + 333) / ((50 * layers) + 365);
}

@Override
public Vector3f getDebrisColor(BlockState blockState, BlockPos position, BlockGetter level) {
return color;
}

private static VoxelShape getShapeForLayerCount(int layers) {
return box(0, 0, 0, 16, 2 * layers, 16);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package io.github.foundationgames.automobility.block;

import com.mojang.serialization.MapCodec;
import io.github.foundationgames.automobility.util.AUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.BlockItemStateProperties;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.joml.Vector3f;

public class OffroadAreaBlock extends Block implements SimpleWaterloggedBlock, OffroadBlock {
public static final int MAX_STRENGTH = 8;
public static final MapCodec<OffroadAreaBlock> CODEC = Block.simpleCodec(OffroadAreaBlock::new);
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public static final IntegerProperty STRENGTH = IntegerProperty.create("strength", 1, MAX_STRENGTH);
public MapCodec<OffroadAreaBlock> codec() {
return CODEC;
}

public OffroadAreaBlock(BlockBehaviour.Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(WATERLOGGED, false).setValue(STRENGTH, 4));
}

protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(WATERLOGGED);
builder.add(STRENGTH);
}

protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (!level.isClientSide && player.canUseGameMasterBlocks()) {
return InteractionResult.SUCCESS;
} else {
return InteractionResult.CONSUME;
}
}

protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return context.isHoldingItem(asItem()) ? Shapes.block() : Shapes.empty();
}

protected boolean propagatesSkylightDown(BlockState state, BlockGetter level, BlockPos pos) {
return state.getFluidState().isEmpty();
}

protected RenderShape getRenderShape(BlockState state) {
return RenderShape.INVISIBLE;
}

protected float getShadeBrightness(BlockState state, BlockGetter level, BlockPos pos) {
return 1.0F;
}

protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
if (state.getValue(WATERLOGGED)) {
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
}

return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
}

protected FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
}

public ItemStack getCloneItemStack(LevelReader level, BlockPos pos, BlockState state) {
return setStrengthOnStack(super.getCloneItemStack(level, pos, state), (Integer)state.getValue(STRENGTH));
}

public static ItemStack setStrengthOnStack(ItemStack stack, int strength) {
stack.set(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY.with(STRENGTH, strength));
return stack;
}

@Override
public float getSpeedMultiplier(BlockState blockState) {
int strength = blockState.getValue(OffroadAreaBlock.STRENGTH);
return (float) ((-40 * strength) + 333) / ((50 * strength) + 365);
}

@Override
public Vector3f getDebrisColor(BlockState blockState, BlockPos position, BlockGetter level) {
return AUtils.colorFromInt(level.getBlockState(position.below()).getMapColor(level, position).col);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.github.foundationgames.automobility.block;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
import org.joml.Vector3f;

public interface OffroadBlock {
float getSpeedMultiplier(BlockState blockState);
Vector3f getDebrisColor(BlockState blockState, BlockPos position, BlockGetter level);
}
Loading