Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #17 - add defaultSpeedLimit setting #24

Merged
merged 2 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/main/java/net/pcal/highspeed/HighspeedConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ public record HighspeedConfig(
List<HighspeedBlockConfig> blockConfigs,
boolean isSpeedometerEnabled,
boolean isTrueSpeedometerEnabled,
boolean isIceBoatsEnabled
boolean isIceBoatsEnabled,
Integer defaultSpeedLimit
) {

public record HighspeedBlockConfig(
ResourceLocation blockId,
int cartSpeed
Integer speedLimit
) {
}
}

9 changes: 6 additions & 3 deletions src/main/java/net/pcal/highspeed/HighspeedConfigParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static HighspeedConfig parse(final InputStream in) throws IOException {
for (HighspeedBlockConfigGson blockGson : configGson.blocks) {
HighspeedBlockConfig bc = new HighspeedBlockConfig(
ResourceLocation.parse(requireNonNull(blockGson.blockId, "blockId is required")),
requireNonNull(blockGson.cartSpeed)
blockGson.cartSpeed != null ? blockGson.cartSpeed : blockGson.speedLimit
);
blocks.add(bc);
}
Expand All @@ -34,7 +34,8 @@ static HighspeedConfig parse(final InputStream in) throws IOException {
Collections.unmodifiableList(blocks),
requireNonNull(configGson.isSpeedometerEnabled, "isSpeedometerEnabled must be set"),
requireNonNull(configGson.isTrueSpeedometerEnabled, "isTrueSpeedometerEnabled must be set"),
requireNonNull(configGson.isIceBoatsEnabled, "isIceBoatsEnabled must be set")
requireNonNull(configGson.isIceBoatsEnabled, "isIceBoatsEnabled must be set"),
configGson.defaultSpeedLimit // may be null
);
}

Expand All @@ -59,10 +60,12 @@ public static class HighspeedConfigGson {
Boolean isSpeedometerEnabled;
Boolean isTrueSpeedometerEnabled;
Boolean isIceBoatsEnabled;
Integer defaultSpeedLimit;
}

public static class HighspeedBlockConfigGson {
String blockId;
Integer cartSpeed;
Integer speedLimit;
Integer cartSpeed; // for backward compat
}
}
21 changes: 15 additions & 6 deletions src/main/java/net/pcal/highspeed/HighspeedService.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package net.pcal.highspeed;

import com.google.common.collect.ImmutableMap;
import net.fabricmc.api.ModInitializer;
import net.minecraft.resources.ResourceLocation;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Map;

import static java.util.Objects.requireNonNull;

Expand All @@ -19,6 +22,7 @@ public class HighspeedService implements ModInitializer {
private static HighspeedService INSTANCE = null;
private HighspeedConfig config;
private HighspeedClientService clientService;
private Map<ResourceLocation, Integer> speedLimitPerBlock;

public static HighspeedService getInstance() {
return requireNonNull(INSTANCE);
Expand Down Expand Up @@ -50,6 +54,11 @@ public void onInitialize() {
} catch (IOException e) {
throw new RuntimeException(e);
}

final ImmutableMap.Builder<ResourceLocation, Integer> b = ImmutableMap.builder();
this.config.blockConfigs().forEach(bc->b.put(bc.blockId(), bc.speedLimit()));
this.speedLimitPerBlock = b.build();

if (INSTANCE != null) throw new IllegalStateException();
INSTANCE = this;
}
Expand All @@ -62,11 +71,12 @@ public void initClientService(HighspeedClientService clientService) {
// ===================================================================================
// Public methods

public Integer getCartSpeed(ResourceLocation id) {
for (HighspeedConfig.HighspeedBlockConfig bc : this.config.blockConfigs()) {
if (id.equals(bc.blockId())) return bc.cartSpeed();
}
return null;
/**
* @return the maximum speed (in blocks-per-second) that a cart travelling on a rail sitting
* on the given block type can travel at. Returns null if the vanilla default should be used.
*/
public Integer getSpeedLimit(ResourceLocation blockId) {
return this.speedLimitPerBlock.getOrDefault(blockId, this.config.defaultSpeedLimit());
}

public boolean isSpeedometerEnabled() {
Expand All @@ -85,5 +95,4 @@ public HighspeedClientService getClientService() {
if (this.clientService == null) throw new UnsupportedOperationException("clientService not initialized");
return this.clientService;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public abstract class AbstractMinecartEntityMixin {
private static final double SQRT_TWO = 1.414213;

private BlockPos lastPos = null;
private double maxSpeed = VANILLA_MAX_SPEED;
private double currentMaxSpeed = VANILLA_MAX_SPEED;
private double lastMaxSpeed = VANILLA_MAX_SPEED;
private Vec3 lastSpeedPos = null;
private long lastSpeedTime = 0;
Expand Down Expand Up @@ -54,7 +54,7 @@ protected void getMaxSpeed(CallbackInfoReturnable<Double> cir) {

private double getModifiedMaxSpeed() {
final BlockPos currentPos = minecart.blockPosition();
if (currentPos.equals(lastPos)) return maxSpeed;
if (currentPos.equals(lastPos)) return currentMaxSpeed;
lastPos = currentPos;
// look at the *next* block the cart is going to hit
final Vec3 v = minecart.getDeltaMovement();
Expand All @@ -67,19 +67,19 @@ private double getModifiedMaxSpeed() {
if (nextState.getBlock() instanceof BaseRailBlock rail) {
final RailShape shape = nextState.getValue(rail.getShapeProperty());
if (shape == RailShape.NORTH_EAST || shape == RailShape.NORTH_WEST || shape == RailShape.SOUTH_EAST || shape == RailShape.SOUTH_WEST) {
return maxSpeed = VANILLA_MAX_SPEED;
return currentMaxSpeed = VANILLA_MAX_SPEED;
} else {
final BlockState underState = minecart.level().getBlockState(currentPos.below());
final ResourceLocation underBlockId = BuiltInRegistries.BLOCK.getKey(underState.getBlock());
final Integer cartSpeedBps = HighspeedService.getInstance().getCartSpeed(underBlockId);
if (cartSpeedBps != null) {
return maxSpeed = cartSpeedBps / 20.0;
final Integer speedLimit = HighspeedService.getInstance().getSpeedLimit(underBlockId);
if (speedLimit != null) {
return currentMaxSpeed = speedLimit / 20.0;
} else {
return maxSpeed = VANILLA_MAX_SPEED;
return currentMaxSpeed = VANILLA_MAX_SPEED;
}
}
} else {
return maxSpeed = VANILLA_MAX_SPEED;
return currentMaxSpeed = VANILLA_MAX_SPEED;
}
}

Expand All @@ -90,7 +90,7 @@ private void clampVelocity() {
minecart.setDeltaMovement(new Vec3(Mth.clamp(vel.x, -smaller, smaller), 0.0,
Mth.clamp(vel.z, -smaller, smaller)));
}
lastMaxSpeed = maxSpeed;
lastMaxSpeed = currentMaxSpeed;
}

private void updateSpeedometer() {
Expand Down
31 changes: 20 additions & 11 deletions src/main/resources/net/pcal/highspeed/default-config.json5
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
// NOTE: This is not actually json5 - it's parsed with minecraft's built-in json parser but with
// some preprocessing to allow for '//' -style comments like this one. The lie in the .json5
// some preprocessing to allow for '//' -style comments like this one. The lie in the .json5
// extension just helps text editors deal with it.
{


//
// List of blocks and how they affect a train travelling on top. cartSpeed is in blocks-per-second.
//
// Sets the maximum speed (in blocks-per-second) for carts travelling on specific blocks. The speedLimit in
// Vanilla is 8.
'blocks' : [
{
'blockId': 'minecraft:gravel',
'cartSpeed': 40
'blockId': 'minecraft:gravel',
'speedLimit': 40
},
{
'blockId': 'minecraft:slime_block',
'speedLimit': 4
}
],

// Whether a speedometer should be displayed when you get in a minecart.
// Sets the default maximum speed for blocks not configured above. A value of 'null' here means to use the
// Vanilla speedLimit (8).
//
// The mod must be installed on the client for this to work.
// If you change this, you should also configure at least one kind of block to maintain Vanilla speed (i.e.,
// by setting 'speedLimit' for a block to be 8 (or null) in the 'blocks' section above). Experience shows that
// carts can derail or reverse unexpectedly in certain situations when travelling above the Vanilla speed limit,
// so you'll want to have at least one block type that can act as a 'brake.'
'defaultSpeedLimit' : null,

// Whether a speedometer should be displayed when you get in a minecart. The mod must be installed on the client
// in order for this to work.
'isSpeedometerEnabled' : true,

// Whether the 'true' speed should also be displayed on the speedometer. The deafult speedometer just shows your
// Whether the 'true' speed should also be displayed on the speedometer. The default speedometer just shows your
// approximate speed; this precisely measures distance travelled every tick. It's more resource-intensive
// and also flickers sort of annoyingly, so disabled by default. There's usually not much difference, anyway.
'isTrueSpeedometerEnabled' : false,

// Whether Vanilla ice boats should be allowed. Set to 'false' to limit ice boats to ground speed; 'true'
//
// The mod must be installed on the client for this to work.
'isIceBoatsEnabled' : false
}