Client-side weather and better time handling

- Weather can now also be changed client side
  - Corresponding /cweather command
- Now optionally works in singleplayer
- /ctime command works again
- Custom time is now a slider in the config screen
This commit is contained in:
Motschen
2023-05-24 18:10:38 +02:00
parent 07e80749d6
commit 366bc058a5
9 changed files with 131 additions and 45 deletions

View File

@@ -3,15 +3,15 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/develop/
minecraft_version=1.19
yarn_mappings=1.19+build.4
loader_version=0.14.8
minecraft_version=1.19.4
yarn_mappings=1.19.4+build.2
loader_version=0.14.19
# Mod Properties
mod_version = 1.2.0
mod_version = 1.3.0
maven_group = eu.midnightdust
archives_base_name = timechanger
# Dependencies
fabric_version=0.56.0+1.19
midnightlib_version = 0.5.2
fabric_version=0.81.1+1.19.4
midnightlib_version=1.3.0-fabric

View File

@@ -1,18 +1,32 @@
package eu.midnightdust.timechanger;
import eu.midnightdust.timechanger.command.CTimeCommand;
import eu.midnightdust.timechanger.command.CWeatherCommand;
import eu.midnightdust.timechanger.config.TimeChangerConfig;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.minecraft.client.MinecraftClient;
public class TimeChangerClient implements ClientModInitializer {
private static MinecraftClient client = MinecraftClient.getInstance();
@Override
public void onInitializeClient() {
TimeChangerConfig.init("timechanger", TimeChangerConfig.class);
if (ClientCommandManager.getActiveDispatcher() != null)
ClientCommandManager.getActiveDispatcher().register(ClientCommandManager.literal("ctime")
.then(CTimeCommand.command())
);
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(CTimeCommand.command()));
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(CWeatherCommand.command()));
}
public static boolean isEnabledOnWorld() {
if (client.getCurrentServerEntry() != null) {
if (TimeChangerConfig.allowlist.isEmpty()) {
return true;
} else if (client.getCurrentServerEntry().address != null) {
if (!TimeChangerConfig.blocklist && TimeChangerConfig.allowlist.contains(client.getCurrentServerEntry().address)) {
return true;
} else return TimeChangerConfig.blocklist && !TimeChangerConfig.allowlist.contains(client.getCurrentServerEntry().address);
}
return false;
}
return TimeChangerConfig.enableInSingleplayer;
}
}

View File

@@ -12,7 +12,7 @@ import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.arg
public class CTimeCommand {
public static LiteralArgumentBuilder<FabricClientCommandSource> command() {
return ClientCommandManager.literal("set").then(
return ClientCommandManager.literal("ctime").then(
argument("time", IntegerArgumentType.integer(-1))
.executes(ctx -> setTime(ctx.getSource(), IntegerArgumentType.getInteger(ctx, "time")))
);
@@ -22,7 +22,7 @@ public class CTimeCommand {
TimeChangerConfig.custom_time = time;
TimeChangerConfig.write("timechanger");
source.sendFeedback(Text.translatable("command.timechanger.ctime.success").append(String.valueOf(time)));
source.sendFeedback(Text.translatable("command.timechanger.ctime.success").append(time >= 0 ? String.valueOf(time) : "disabled"));
return 1;
}

View File

@@ -0,0 +1,29 @@
package eu.midnightdust.timechanger.command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import eu.midnightdust.timechanger.config.TimeChangerConfig;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
public class CWeatherCommand {
public static LiteralArgumentBuilder<FabricClientCommandSource> command() {
return ClientCommandManager.literal("cweather")
.then(literal("unset").executes(ctx -> setWeather(ctx.getSource(), TimeChangerConfig.Weather.UNSET)))
.then(literal("clear").executes(ctx -> setWeather(ctx.getSource(), TimeChangerConfig.Weather.CLEAR)))
.then(literal("rain").executes(ctx -> setWeather(ctx.getSource(), TimeChangerConfig.Weather.RAIN)))
.then(literal("thunder").executes(ctx -> setWeather(ctx.getSource(), TimeChangerConfig.Weather.THUNDER)));
}
private static int setWeather(FabricClientCommandSource source, TimeChangerConfig.Weather weather) {
TimeChangerConfig.custom_weather = weather;
TimeChangerConfig.write("timechanger");
source.sendFeedback(Text.translatable("command.timechanger.cweather.success").append(String.valueOf(weather)));
return 1;
}
}

View File

@@ -6,7 +6,13 @@ import java.util.ArrayList;
import java.util.List;
public class TimeChangerConfig extends MidnightConfig {
@Entry public static int custom_time = -1;
@Entry(isSlider = true, min = -1, max = 24000) public static int custom_time = -1;
@Entry public static Weather custom_weather = Weather.UNSET;
@Entry public static List<String> allowlist = new ArrayList<>();
@Entry public static boolean blocklist = false;
@Entry public static boolean enableInSingleplayer = false;
public enum Weather {
UNSET, CLEAR, RAIN, THUNDER;
}
}

View File

@@ -1,40 +1,43 @@
package eu.midnightdust.timechanger.mixin;
import eu.midnightdust.timechanger.TimeChangerClient;
import eu.midnightdust.timechanger.config.TimeChangerConfig;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Final;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.profiler.Profiler;
import net.minecraft.world.MutableWorldProperties;
import net.minecraft.world.World;
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(ClientWorld.class)
public abstract class MixinClientWorld {
public abstract class MixinClientWorld extends World {
@Shadow @Final private ClientWorld.Properties clientWorldProperties;
@Shadow @Final private MinecraftClient client;
@Inject(at = @At("TAIL"), method = "setTimeOfDay", cancellable = true)
@Environment(EnvType.CLIENT)
public void setTimeOfDay(long time, CallbackInfo ci) {
if (client.getCurrentServerEntry() != null) {
if (TimeChangerConfig.custom_time >= 0 && TimeChangerConfig.allowlist.isEmpty()) {
this.clientWorldProperties.setTimeOfDay(TimeChangerConfig.custom_time);
} else if (TimeChangerConfig.custom_time >= 0 && client.getCurrentServerEntry().address != null) {
if (!TimeChangerConfig.blocklist && TimeChangerConfig.allowlist.contains(client.getCurrentServerEntry().address)) {
this.clientWorldProperties.setTimeOfDay(TimeChangerConfig.custom_time);
} else if (TimeChangerConfig.blocklist && !TimeChangerConfig.allowlist.contains(client.getCurrentServerEntry().address)) {
this.clientWorldProperties.setTimeOfDay(TimeChangerConfig.custom_time);
}
else {ci.cancel();}
}
else {ci.cancel();}
protected MixinClientWorld(MutableWorldProperties properties, RegistryKey<World> registryRef, DynamicRegistryManager registryManager, RegistryEntry<DimensionType> dimensionEntry, Supplier<Profiler> profiler, boolean isClient, boolean debugWorld, long biomeAccess, int maxChainedNeighborUpdates) {
super(properties, registryRef, registryManager, dimensionEntry, profiler, isClient, debugWorld, biomeAccess, maxChainedNeighborUpdates);
}
@Override
public float getRainGradient(float delta) {
if (TimeChangerClient.isEnabledOnWorld() && !TimeChangerConfig.custom_weather.equals(TimeChangerConfig.Weather.UNSET)) {
if (TimeChangerConfig.custom_weather.equals(TimeChangerConfig.Weather.CLEAR)) {
return 0f;
} else return 1f;
}
else {ci.cancel();}
return super.getRainGradient(delta);
}
@Override
public float getThunderGradient(float delta) {
if (TimeChangerClient.isEnabledOnWorld() && !TimeChangerConfig.custom_weather.equals(TimeChangerConfig.Weather.UNSET)) {
if (TimeChangerConfig.custom_weather.equals(TimeChangerConfig.Weather.THUNDER)) {
return 1f;
} else return 0f;
}
return super.getRainGradient(delta);
}
}

View File

@@ -0,0 +1,25 @@
package eu.midnightdust.timechanger.mixin;
import eu.midnightdust.timechanger.TimeChangerClient;
import eu.midnightdust.timechanger.config.TimeChangerConfig;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.world.ClientWorld;
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(ClientWorld.Properties.class)
public abstract class MixinClientWorldProperties {
@Inject(at = @At("RETURN"), method = "getTimeOfDay", cancellable = true)
@Environment(EnvType.CLIENT)
public void getTimeOfDay(CallbackInfoReturnable<Long> cir) {
if (TimeChangerClient.isEnabledOnWorld() && TimeChangerConfig.custom_time >= 0) {
cir.setReturnValue((long) TimeChangerConfig.custom_time);
}
else cir.cancel();
}
}

View File

@@ -2,7 +2,15 @@
"timechanger.midnightconfig.title":"Time Changer Config",
"timechanger.midnightconfig.custom_time":"Custom Time",
"timechanger.midnightconfig.custom_time.tooltip": "Set the Custom Time (-1 to disable)",
"timechanger.midnightconfig.custom_weather":"Custom Weather",
"timechanger.midnightconfig.custom_weather.tooltip": "Set the Custom Time (Unset to disable)",
"timechanger.midnightconfig.enum.Weather.UNSET":"Unset",
"timechanger.midnightconfig.enum.Weather.CLEAR":"Clear",
"timechanger.midnightconfig.enum.Weather.RAIN":"Rain",
"timechanger.midnightconfig.enum.Weather.THUNDER":"Thunder",
"timechanger.midnightconfig.allowlist":"Server Allowlist",
"timechanger.midnightconfig.blocklist":"Use Allowlist as Blocklist?",
"command.timechanger.ctime.success": "Successfully set the client time to "
"timechanger.midnightconfig.enableInSingleplayer":"Enable in Singleplayer?",
"command.timechanger.ctime.success": "Successfully set the client time to ",
"command.timechanger.cweather.success": "Successfully set the client weather to "
}

View File

@@ -1,9 +1,10 @@
{
"required": true,
"package": "eu.midnightdust.timechanger.mixin",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_17",
"client": [
"MixinClientWorld"
"MixinClientWorld",
"MixinClientWorldProperties"
],
"injectors": {
"defaultRequire": 1