mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-30 17:06:56 +01:00
all the configs
- make it easier for addon devs to hook into create's config ui - change the config command to allow for: - opening any mod's registered config - changing single values at a time - possibly solve incompatibility with CalemiUtils mod and placement helpers
This commit is contained in:
parent
2e37807e7f
commit
975d898ac6
12 changed files with 468 additions and 76 deletions
|
@ -339,8 +339,8 @@ public class ClientEvents {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadCompleted(FMLLoadCompleteEvent event) {
|
public static void loadCompleted(FMLLoadCompleteEvent event) {
|
||||||
ModContainer createContainer = ModList.get().getModContainerById("create").orElseThrow(() -> new IllegalStateException("Create Mod Container missing after loadCompleted"));
|
ModContainer createContainer = ModList.get().getModContainerById(Create.ID).orElseThrow(() -> new IllegalStateException("Create Mod Container missing after loadCompleted"));
|
||||||
createContainer.registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (mc, previousScreen) -> new BaseConfigScreen(previousScreen));
|
createContainer.registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (mc, previousScreen) -> BaseConfigScreen.forCreate(previousScreen));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,25 @@
|
||||||
package com.simibubi.create.foundation.command;
|
package com.simibubi.create.foundation.command;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.Command;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.foundation.config.ui.ConfigHelper;
|
||||||
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.command.CommandSource;
|
||||||
import net.minecraft.command.Commands;
|
import net.minecraft.command.Commands;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import net.minecraftforge.fml.network.PacketDistributor;
|
import net.minecraftforge.fml.network.PacketDistributor;
|
||||||
|
|
||||||
import com.mojang.brigadier.Command;
|
/**
|
||||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
* Examples:
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
* /create config client - to open Create's ConfigGui with the client config already selected
|
||||||
|
* /create config "botania:common" - to open Create's ConfigGui with Botania's common config already selected
|
||||||
|
* /create config "create:client.client.rainbowDebug" set false - to disable Create's rainbow debug for the sender
|
||||||
|
*/
|
||||||
public class ConfigCommand {
|
public class ConfigCommand {
|
||||||
|
|
||||||
public static ArgumentBuilder<CommandSource, ?> register() {
|
public static ArgumentBuilder<CommandSource, ?> register() {
|
||||||
|
@ -21,7 +32,59 @@ public class ConfigCommand {
|
||||||
);
|
);
|
||||||
|
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
});
|
})
|
||||||
|
.then(Commands.argument("path", StringArgumentType.string())
|
||||||
|
.executes(ctx -> {
|
||||||
|
ServerPlayerEntity player = ctx.getSource().asPlayer();
|
||||||
|
AllPackets.channel.send(
|
||||||
|
PacketDistributor.PLAYER.with(() -> player),
|
||||||
|
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.configScreen.name(), StringArgumentType.getString(ctx, "path"))
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
.then(Commands.literal("set")
|
||||||
|
.requires(cs -> cs.hasPermissionLevel(2))
|
||||||
|
.then(Commands.argument("value", StringArgumentType.string())
|
||||||
|
.executes(ctx -> {
|
||||||
|
String path = StringArgumentType.getString(ctx, "path");
|
||||||
|
String value = StringArgumentType.getString(ctx, "value");
|
||||||
|
|
||||||
|
|
||||||
|
ConfigHelper.ConfigPath configPath;
|
||||||
|
try {
|
||||||
|
configPath = ConfigHelper.ConfigPath.parse(path);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
ctx.getSource().sendErrorMessage(new StringTextComponent(e.getMessage()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configPath.getType() == ModConfig.Type.CLIENT) {
|
||||||
|
ServerPlayerEntity player = ctx.getSource().asPlayer();
|
||||||
|
AllPackets.channel.send(
|
||||||
|
PacketDistributor.PLAYER.with(() -> player),
|
||||||
|
new SConfigureConfigPacket("SET" + path, value)
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ConfigHelper.setConfigValue(configPath, value);
|
||||||
|
ctx.getSource().sendFeedback(new StringTextComponent("Great Success!"), false);
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
} catch (ConfigHelper.InvalidValueException e) {
|
||||||
|
ctx.getSource().sendErrorMessage(new StringTextComponent("Config could not be set the the specified value!"));
|
||||||
|
return 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
ctx.getSource().sendErrorMessage(new StringTextComponent("Something went wrong while trying to set config value. Check the server logs for more information"));
|
||||||
|
Create.LOGGER.warn("Exception during server-side config value set:", e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
|
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
|
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
|
||||||
|
import com.simibubi.create.foundation.config.ui.ConfigHelper;
|
||||||
|
import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen;
|
||||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||||
import com.simibubi.create.foundation.ponder.PonderRegistry;
|
import com.simibubi.create.foundation.ponder.PonderRegistry;
|
||||||
|
@ -30,6 +32,7 @@ import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.common.ForgeConfig;
|
import net.minecraftforge.common.ForgeConfig;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
|
|
||||||
public class SConfigureConfigPacket extends SimplePacketBase {
|
public class SConfigureConfigPacket extends SimplePacketBase {
|
||||||
|
@ -57,6 +60,11 @@ public class SConfigureConfigPacket extends SimplePacketBase {
|
||||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||||
ctx.get()
|
ctx.get()
|
||||||
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||||
|
if (option.startsWith("SET")) {
|
||||||
|
trySetConfig(option.substring(3), value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Actions.valueOf(option)
|
Actions.valueOf(option)
|
||||||
.performAction(value);
|
.performAction(value);
|
||||||
|
@ -70,6 +78,36 @@ public class SConfigureConfigPacket extends SimplePacketBase {
|
||||||
.setPacketHandled(true);
|
.setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void trySetConfig(String option, String value) {
|
||||||
|
ClientPlayerEntity player = Minecraft.getInstance().player;
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConfigHelper.ConfigPath configPath;
|
||||||
|
try {
|
||||||
|
configPath = ConfigHelper.ConfigPath.parse(option);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
player.sendStatusMessage(new StringTextComponent(e.getMessage()), false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configPath.getType() != ModConfig.Type.CLIENT) {
|
||||||
|
Create.LOGGER.warn("Received type-mismatched config packet on client");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ConfigHelper.setConfigValue(configPath, value);
|
||||||
|
player.sendStatusMessage(new StringTextComponent("Great Success!"), false);
|
||||||
|
} catch (ConfigHelper.InvalidValueException e) {
|
||||||
|
player.sendStatusMessage(new StringTextComponent("Config could not be set the the specified value!"), false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
player.sendStatusMessage(new StringTextComponent("Something went wrong while trying to set config value. Check the client logs for more information"), false);
|
||||||
|
Create.LOGGER.warn("Exception during client-side config value set:", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public enum Actions {
|
public enum Actions {
|
||||||
configScreen(() -> Actions::configScreen),
|
configScreen(() -> Actions::configScreen),
|
||||||
rainbowDebug(() -> Actions::rainbowDebug),
|
rainbowDebug(() -> Actions::rainbowDebug),
|
||||||
|
@ -95,7 +133,25 @@ public class SConfigureConfigPacket extends SimplePacketBase {
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
private static void configScreen(String value) {
|
private static void configScreen(String value) {
|
||||||
ScreenOpener.open(new BaseConfigScreen(null));
|
if (value.equals("")) {
|
||||||
|
ScreenOpener.open(BaseConfigScreen.forCreate(null));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientPlayerEntity player = Minecraft.getInstance().player;
|
||||||
|
ConfigHelper.ConfigPath configPath;
|
||||||
|
try {
|
||||||
|
configPath = ConfigHelper.ConfigPath.parse(value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
player.sendStatusMessage(new StringTextComponent(e.getMessage()), false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ScreenOpener.open(SubMenuConfigScreen.find(configPath));
|
||||||
|
} catch (Exception e) {
|
||||||
|
player.sendStatusMessage(new StringTextComponent("Unable to find the specified config"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package com.simibubi.create.foundation.config.ui;
|
package com.simibubi.create.foundation.config.ui;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
|
||||||
import com.simibubi.create.foundation.gui.ScreenOpener;
|
import com.simibubi.create.foundation.gui.ScreenOpener;
|
||||||
import com.simibubi.create.foundation.gui.TextStencilElement;
|
import com.simibubi.create.foundation.gui.TextStencilElement;
|
||||||
import com.simibubi.create.foundation.gui.Theme;
|
import com.simibubi.create.foundation.gui.Theme;
|
||||||
|
@ -11,49 +16,134 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraft.util.text.TextFormatting;
|
import net.minecraft.util.text.TextFormatting;
|
||||||
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
|
|
||||||
public class BaseConfigScreen extends ConfigScreen {
|
public class BaseConfigScreen extends ConfigScreen {
|
||||||
|
|
||||||
|
private static final DelegatedStencilElement.ElementRenderer DISABLED_RENDERER = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.BUTTON_DISABLE, true), Theme.i(Theme.Key.BUTTON_DISABLE, false) | 0x40_000000);
|
||||||
|
|
||||||
|
public static BaseConfigScreen forCreate(Screen parent) {
|
||||||
|
return new BaseConfigScreen(parent)
|
||||||
|
.withTitles("Client Settings", "World Generation Settings", "Gameplay Settings")
|
||||||
|
.withSpecs(AllConfigs.CLIENT.specification, AllConfigs.COMMON.specification, AllConfigs.SERVER.specification);
|
||||||
|
}
|
||||||
|
|
||||||
BoxWidget clientConfigWidget;
|
BoxWidget clientConfigWidget;
|
||||||
BoxWidget commonConfigWidget;
|
BoxWidget commonConfigWidget;
|
||||||
BoxWidget serverConfigWidget;
|
BoxWidget serverConfigWidget;
|
||||||
|
|
||||||
public BaseConfigScreen(Screen parent) {
|
ForgeConfigSpec clientSpec;
|
||||||
|
ForgeConfigSpec commonSpec;
|
||||||
|
ForgeConfigSpec serverSpec;
|
||||||
|
String clientTile = "CLIENT CONFIG";
|
||||||
|
String commonTile = "COMMON CONFIG";
|
||||||
|
String serverTile = "SERVER CONFIG";
|
||||||
|
String modID = Create.ID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you are a Create Addon dev and want to make use of the same GUI
|
||||||
|
* for your mod's config, use this Constructor to create a entry point
|
||||||
|
*
|
||||||
|
* @param parent the previously opened screen
|
||||||
|
* @param modID the modID of your addon/mod
|
||||||
|
*/
|
||||||
|
public BaseConfigScreen(Screen parent, @Nonnull String modID) {
|
||||||
|
this(parent);
|
||||||
|
this.modID = modID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseConfigScreen(Screen parent) {
|
||||||
super(parent);
|
super(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you have static references to your Configs or ConfigSpecs (like Create does in {@link AllConfigs}),
|
||||||
|
* please use {@link #withSpecs(ForgeConfigSpec, ForgeConfigSpec, ForgeConfigSpec)} instead
|
||||||
|
*/
|
||||||
|
public BaseConfigScreen searchForSpecsInModContainer() {
|
||||||
|
try {
|
||||||
|
clientSpec = ConfigHelper.findConfigSpecFor(ModConfig.Type.CLIENT, this.modID);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Create.LOGGER.warn("Unable to find ClientConfigSpec for mod: " + this.modID);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
commonSpec = ConfigHelper.findConfigSpecFor(ModConfig.Type.COMMON, this.modID);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Create.LOGGER.warn("Unable to find CommonConfigSpec for mod: " + this.modID, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
serverSpec = ConfigHelper.findConfigSpecFor(ModConfig.Type.SERVER, this.modID);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Create.LOGGER.warn("Unable to find ServerConfigSpec for mod: " + this.modID, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseConfigScreen withSpecs(@Nullable ForgeConfigSpec client, @Nullable ForgeConfigSpec common, @Nullable ForgeConfigSpec server) {
|
||||||
|
clientSpec = client;
|
||||||
|
commonSpec = common;
|
||||||
|
serverSpec = server;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseConfigScreen withTitles(@Nullable String client, @Nullable String common, @Nullable String server) {
|
||||||
|
if (client != null)
|
||||||
|
clientTile = client;
|
||||||
|
|
||||||
|
if (common != null)
|
||||||
|
commonTile = common;
|
||||||
|
|
||||||
|
if (server != null)
|
||||||
|
serverTile = server;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
widgets.clear();
|
widgets.clear();
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
TextStencilElement text = new TextStencilElement(client.fontRenderer, new StringTextComponent("Client Settings").formatted(TextFormatting.BOLD)).centered(true, true);
|
TextStencilElement clientText = new TextStencilElement(client.fontRenderer, new StringTextComponent(clientTile).formatted(TextFormatting.BOLD)).centered(true, true);
|
||||||
widgets.add(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16)
|
widgets.add(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16).showingElement(clientText));
|
||||||
.showingElement(text)
|
|
||||||
.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification)))
|
|
||||||
);
|
|
||||||
text.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget));
|
|
||||||
|
|
||||||
TextStencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("World Generation Settings").formatted(TextFormatting.BOLD)).centered(true, true);
|
if (clientSpec != null) {
|
||||||
widgets.add(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16)
|
clientConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, clientSpec)));
|
||||||
.showingElement(text2)
|
clientText.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget));
|
||||||
.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification)))
|
} else {
|
||||||
);
|
clientConfigWidget.active = false;
|
||||||
text2.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget));
|
clientConfigWidget.updateColorsFromState();
|
||||||
|
clientText.withElementRenderer(DISABLED_RENDERER);
|
||||||
|
}
|
||||||
|
|
||||||
TextStencilElement text3 = new TextStencilElement(client.fontRenderer, new StringTextComponent("Gameplay Settings").formatted(TextFormatting.BOLD)).centered(true, true);
|
TextStencilElement commonText = new TextStencilElement(client.fontRenderer, new StringTextComponent(commonTile).formatted(TextFormatting.BOLD)).centered(true, true);
|
||||||
widgets.add(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16)
|
widgets.add(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16).showingElement(commonText));
|
||||||
.showingElement(text3)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Minecraft.getInstance().world != null) {
|
if (commonSpec != null) {
|
||||||
serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, AllConfigs.SERVER.specification)));
|
commonConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, commonSpec)));
|
||||||
text3.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget));
|
commonText.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget));
|
||||||
|
} else {
|
||||||
|
commonConfigWidget.active = false;
|
||||||
|
commonConfigWidget.updateColorsFromState();
|
||||||
|
commonText.withElementRenderer(DISABLED_RENDERER);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStencilElement serverText = new TextStencilElement(client.fontRenderer, new StringTextComponent(serverTile).formatted(TextFormatting.BOLD)).centered(true, true);
|
||||||
|
widgets.add(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16).showingElement(serverText));
|
||||||
|
|
||||||
|
if (serverSpec != null && Minecraft.getInstance().world != null) {
|
||||||
|
serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, serverSpec)));
|
||||||
|
serverText.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget));
|
||||||
} else {
|
} else {
|
||||||
serverConfigWidget.active = false;
|
serverConfigWidget.active = false;
|
||||||
serverConfigWidget.updateColorsFromState();
|
serverConfigWidget.updateColorsFromState();
|
||||||
text3.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.BUTTON_DISABLE, true), Theme.i(Theme.Key.BUTTON_DISABLE, false) | 0x40_000000));
|
serverText.withElementRenderer(DISABLED_RENDERER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigScreen.modID = this.modID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,65 @@
|
||||||
package com.simibubi.create.foundation.config.ui;
|
package com.simibubi.create.foundation.config.ui;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.command.SConfigureConfigPacket;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
|
||||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||||
|
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
import net.minecraftforge.fml.network.PacketDistributor;
|
|
||||||
|
|
||||||
public class CConfigureConfigPacket<T> extends SimplePacketBase {
|
public class CConfigureConfigPacket<T> extends SimplePacketBase {
|
||||||
|
|
||||||
|
private String modID;
|
||||||
private String path;
|
private String path;
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
public CConfigureConfigPacket(String path, T value) {
|
public CConfigureConfigPacket(String modID, String path, T value) {
|
||||||
|
this.modID = Objects.requireNonNull(modID);
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.value = serialize(value);
|
this.value = serialize(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CConfigureConfigPacket(PacketBuffer buffer) {
|
public CConfigureConfigPacket(PacketBuffer buffer) {
|
||||||
|
this.modID = buffer.readString(32767);
|
||||||
this.path = buffer.readString(32767);
|
this.path = buffer.readString(32767);
|
||||||
this.value = buffer.readString(32767);
|
this.value = buffer.readString(32767);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(PacketBuffer buffer) {
|
public void write(PacketBuffer buffer) {
|
||||||
|
buffer.writeString(modID);
|
||||||
buffer.writeString(path);
|
buffer.writeString(path);
|
||||||
buffer.writeString(value);
|
buffer.writeString(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(Supplier<NetworkEvent.Context> context) {
|
public void handle(Supplier<NetworkEvent.Context> context) {
|
||||||
ServerPlayerEntity sender = context.get().getSender();
|
context.get().enqueueWork(() -> {
|
||||||
if (sender == null || !sender.hasPermissionLevel(2))
|
try {
|
||||||
return;
|
ServerPlayerEntity sender = context.get().getSender();
|
||||||
|
if (sender == null || !sender.hasPermissionLevel(2))
|
||||||
|
return;
|
||||||
|
|
||||||
ForgeConfigSpec.ValueSpec valueSpec = AllConfigs.SERVER.specification.getRaw(path);
|
ForgeConfigSpec spec = ConfigHelper.findConfigSpecFor(ModConfig.Type.SERVER, modID);
|
||||||
ForgeConfigSpec.ConfigValue<T> configValue = AllConfigs.SERVER.specification.getValues().get(path);
|
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(path);
|
||||||
|
ForgeConfigSpec.ConfigValue<T> configValue = spec.getValues().get(path);
|
||||||
|
|
||||||
T v = (T) deserialize(configValue.get(), value);
|
T v = (T) deserialize(configValue.get(), value);
|
||||||
if (!valueSpec.test(v))
|
if (!valueSpec.test(v))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
configValue.set(v);
|
configValue.set(v);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Create.LOGGER.warn("Unable to handle ConfigureConfig Packet. ", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
context.get().setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String serialize(T value) {
|
public String serialize(T value) {
|
||||||
|
@ -66,7 +77,7 @@ public class CConfigureConfigPacket<T> extends SimplePacketBase {
|
||||||
throw new IllegalArgumentException("unknown type " + value + ": " + value.getClass().getSimpleName());
|
throw new IllegalArgumentException("unknown type " + value + ": " + value.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object deserialize(Object type, String sValue) {
|
public static Object deserialize(Object type, String sValue) {
|
||||||
if (type instanceof Boolean)
|
if (type instanceof Boolean)
|
||||||
return Boolean.parseBoolean(sValue);
|
return Boolean.parseBoolean(sValue);
|
||||||
if (type instanceof Enum<?>)
|
if (type instanceof Enum<?>)
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
package com.simibubi.create.foundation.config.ui;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
import net.minecraftforge.fml.ModContainer;
|
||||||
|
import net.minecraftforge.fml.ModList;
|
||||||
|
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||||
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
|
|
||||||
|
public class ConfigHelper {
|
||||||
|
|
||||||
|
private static final LoadingCache<String, EnumMap<ModConfig.Type, ModConfig>> configCache = CacheBuilder.newBuilder().expireAfterAccess(15, TimeUnit.SECONDS).build(
|
||||||
|
new CacheLoader<String, EnumMap<ModConfig.Type, ModConfig>>() {
|
||||||
|
@Override
|
||||||
|
public EnumMap<ModConfig.Type, ModConfig> load(@Nonnull String key) {
|
||||||
|
return findModConfigsUncached(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
private static EnumMap<ModConfig.Type, ModConfig> findModConfigsUncached(String modID) {
|
||||||
|
ModContainer modContainer = ModList.get().getModContainerById(modID).orElseThrow(() -> new IllegalArgumentException("Unable to find ModContainer for id: " + modID));
|
||||||
|
EnumMap<ModConfig.Type, ModConfig> configs = ObfuscationReflectionHelper.getPrivateValue(ModContainer.class, modContainer, "configs");
|
||||||
|
return Objects.requireNonNull(configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ForgeConfigSpec findConfigSpecFor(ModConfig.Type type, String modID) {
|
||||||
|
if (!modID.equals(Create.ID))
|
||||||
|
return configCache.getUnchecked(modID).get(type).getSpec();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case COMMON:
|
||||||
|
return AllConfigs.COMMON.specification;
|
||||||
|
case CLIENT:
|
||||||
|
return AllConfigs.CLIENT.specification;
|
||||||
|
case SERVER:
|
||||||
|
return AllConfigs.SERVER.specification;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Directly set a value
|
||||||
|
public static <T> void setConfigValue(ConfigPath path, String value) throws InvalidValueException {
|
||||||
|
ForgeConfigSpec spec = findConfigSpecFor(path.getType(), path.getModID());
|
||||||
|
List<String> pathList = Arrays.asList(path.getPath());
|
||||||
|
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(pathList);
|
||||||
|
ForgeConfigSpec.ConfigValue<T> configValue = spec.getValues().get(pathList);
|
||||||
|
T v = (T) CConfigureConfigPacket.deserialize(configValue.get(), value);
|
||||||
|
if (!valueSpec.test(v))
|
||||||
|
throw new InvalidValueException();
|
||||||
|
|
||||||
|
configValue.set(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add a value to the current UI's changes list
|
||||||
|
public static <T> void setValue(String path, ForgeConfigSpec.ConfigValue<T> configValue, T value) {
|
||||||
|
if (value.equals(configValue.get())) {
|
||||||
|
ConfigScreen.changes.remove(path);
|
||||||
|
} else {
|
||||||
|
ConfigScreen.changes.put(path, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get a value from the current UI's changes list or the config value, if its unchanged
|
||||||
|
public static <T> T getValue(String path, ForgeConfigSpec.ConfigValue<T> configValue) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) ConfigScreen.changes.getOrDefault(path, configValue.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConfigPath {
|
||||||
|
private String modID = Create.ID;
|
||||||
|
private ModConfig.Type type = ModConfig.Type.CLIENT;
|
||||||
|
private String[] path;
|
||||||
|
|
||||||
|
public static ConfigPath parse(String string) {
|
||||||
|
ConfigPath cp = new ConfigPath();
|
||||||
|
String p = string;
|
||||||
|
int index = string.indexOf(":");
|
||||||
|
if (index >= 0) {
|
||||||
|
p = string.substring(index + 1);
|
||||||
|
if (index >= 1) {
|
||||||
|
cp.modID = string.substring(0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String[] split = p.split("\\.");
|
||||||
|
try {
|
||||||
|
cp.type = ModConfig.Type.valueOf(split[0].toUpperCase(Locale.ROOT));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException("path must start with either 'client.', 'common.' or 'server.'");
|
||||||
|
}
|
||||||
|
|
||||||
|
cp.path = new String[split.length - 1];
|
||||||
|
System.arraycopy(split, 1, cp.path, 0, cp.path.length);
|
||||||
|
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigPath setID(String modID) {
|
||||||
|
this.modID = modID;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigPath setType(ModConfig.Type type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigPath setPath(String[] path) {
|
||||||
|
this.path = path;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModID() {
|
||||||
|
return modID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModConfig.Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InvalidValueException extends Exception {}
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ public abstract class ConfigScreen extends AbstractSimiScreen {
|
||||||
public static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f));
|
public static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f));
|
||||||
public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().with(CogWheelBlock.AXIS, Direction.Axis.Y);
|
public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().with(CogWheelBlock.AXIS, Direction.Axis.Y);
|
||||||
public static final Map<String, Object> changes = new HashMap<>();
|
public static final Map<String, Object> changes = new HashMap<>();
|
||||||
|
public static String modID = null;
|
||||||
protected final Screen parent;
|
protected final Screen parent;
|
||||||
|
|
||||||
public ConfigScreen(Screen parent) {
|
public ConfigScreen(Screen parent) {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package com.simibubi.create.foundation.config.ui;
|
package com.simibubi.create.foundation.config.ui;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -19,10 +21,6 @@ import net.minecraftforge.client.event.GuiScreenEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class OpenConfigButton extends Button {
|
public class OpenConfigButton extends Button {
|
||||||
|
|
||||||
public static ItemStack icon = AllItems.GOGGLES.asStack();
|
public static ItemStack icon = AllItems.GOGGLES.asStack();
|
||||||
|
@ -38,7 +36,7 @@ public class OpenConfigButton extends Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void click(Button b) {
|
public static void click(Button b) {
|
||||||
Minecraft.getInstance().displayGuiScreen(new BaseConfigScreen(Minecraft.getInstance().currentScreen));
|
Minecraft.getInstance().displayGuiScreen(BaseConfigScreen.forCreate(Minecraft.getInstance().currentScreen));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SingleMenuRow {
|
public static class SingleMenuRow {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package com.simibubi.create.foundation.config.ui;
|
package com.simibubi.create.foundation.config.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -9,6 +12,7 @@ import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.AbstractConfig;
|
import com.electronwill.nightconfig.core.AbstractConfig;
|
||||||
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.foundation.config.ui.entries.BooleanEntry;
|
import com.simibubi.create.foundation.config.ui.entries.BooleanEntry;
|
||||||
import com.simibubi.create.foundation.config.ui.entries.EnumEntry;
|
import com.simibubi.create.foundation.config.ui.entries.EnumEntry;
|
||||||
|
@ -50,6 +54,37 @@ public class SubMenuConfigScreen extends ConfigScreen {
|
||||||
protected int listWidth;
|
protected int listWidth;
|
||||||
protected String title;
|
protected String title;
|
||||||
|
|
||||||
|
public static SubMenuConfigScreen find(ConfigHelper.ConfigPath path) {
|
||||||
|
ForgeConfigSpec spec = ConfigHelper.findConfigSpecFor(path.getType(), path.getModID());
|
||||||
|
UnmodifiableConfig values = spec.getValues();
|
||||||
|
BaseConfigScreen base = new BaseConfigScreen(null, path.getModID()).searchForSpecsInModContainer();
|
||||||
|
SubMenuConfigScreen screen = new SubMenuConfigScreen(base, "root", path.getType(), spec, values);
|
||||||
|
List<String> remainingPath = Lists.newArrayList(path.getPath());
|
||||||
|
|
||||||
|
path: while (!remainingPath.isEmpty()) {
|
||||||
|
String next = remainingPath.remove(0);
|
||||||
|
for (Map.Entry<String, Object> entry : values.valueMap().entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
Object obj = entry.getValue();
|
||||||
|
if (!key.equalsIgnoreCase(next))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(obj instanceof AbstractConfig)) {
|
||||||
|
//highlight entry
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
values = (UnmodifiableConfig) obj;
|
||||||
|
screen = new SubMenuConfigScreen(screen, toHumanReadable(key), path.getType(), spec, values);
|
||||||
|
continue path;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigScreen.modID = path.getModID();
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
|
||||||
public SubMenuConfigScreen(Screen parent, String title, ModConfig.Type type, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) {
|
public SubMenuConfigScreen(Screen parent, String title, ModConfig.Type type, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) {
|
||||||
super(parent);
|
super(parent);
|
||||||
|
@ -81,7 +116,7 @@ public class SubMenuConfigScreen extends ConfigScreen {
|
||||||
ForgeConfigSpec.ConfigValue configValue = values.get(path);
|
ForgeConfigSpec.ConfigValue configValue = values.get(path);
|
||||||
configValue.set(value);
|
configValue.set(value);
|
||||||
if (type == ModConfig.Type.SERVER) {
|
if (type == ModConfig.Type.SERVER) {
|
||||||
AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(path, value));
|
AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(ConfigScreen.modID, path, value));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
clearChanges();
|
clearChanges();
|
||||||
|
@ -92,11 +127,10 @@ public class SubMenuConfigScreen extends ConfigScreen {
|
||||||
if (obj instanceof AbstractConfig) {
|
if (obj instanceof AbstractConfig) {
|
||||||
resetConfig((UnmodifiableConfig) obj);
|
resetConfig((UnmodifiableConfig) obj);
|
||||||
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
|
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
|
||||||
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
|
ForgeConfigSpec.ConfigValue configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
|
||||||
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
|
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw((List<String>) configValue.getPath());
|
||||||
|
|
||||||
if (!configValue.get().equals(valueSpec.getDefault()))
|
ConfigHelper.setValue(String.join(".", configValue.getPath()), configValue, valueSpec.getDefault());
|
||||||
changes.put(String.join(".", configValue.getPath()), valueSpec.getDefault());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -265,7 +299,7 @@ public class SubMenuConfigScreen extends ConfigScreen {
|
||||||
super.renderWindow(ms, mouseX, mouseY, partialTicks);
|
super.renderWindow(ms, mouseX, mouseY, partialTicks);
|
||||||
|
|
||||||
int x = width/2;
|
int x = width/2;
|
||||||
drawCenteredString(ms, client.fontRenderer, "Editing config: " + type.toString() + "@" + title, x, 15, Theme.i(Theme.Key.TEXT));
|
drawCenteredString(ms, client.fontRenderer, "Editing config: " + ConfigScreen.modID + ":" + type.toString().toLowerCase(Locale.ROOT) + "@" + title, x, 15, Theme.i(Theme.Key.TEXT));
|
||||||
|
|
||||||
list.render(ms, mouseX, mouseY, partialTicks);
|
list.render(ms, mouseX, mouseY, partialTicks);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import javax.annotation.Nonnull;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.foundation.config.ui.ConfigHelper;
|
||||||
import com.simibubi.create.foundation.config.ui.ConfigScreen;
|
import com.simibubi.create.foundation.config.ui.ConfigScreen;
|
||||||
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
|
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
|
||||||
import com.simibubi.create.foundation.gui.AllIcons;
|
import com.simibubi.create.foundation.gui.AllIcons;
|
||||||
|
@ -115,20 +116,13 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(@Nonnull T value) {
|
public void setValue(@Nonnull T value) {
|
||||||
if (value.equals(this.value.get())) {
|
ConfigHelper.setValue(path, this.value, value);
|
||||||
ConfigScreen.changes.remove(path);
|
|
||||||
onValueChange(value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigScreen.changes.put(path, value);
|
|
||||||
onValueChange(value);
|
onValueChange(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public T getValue() {
|
public T getValue() {
|
||||||
//noinspection unchecked
|
return ConfigHelper.getValue(path, this.value);
|
||||||
return (T) ConfigScreen.changes.getOrDefault(path, this.value.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isCurrentValueChanged() {
|
protected boolean isCurrentValueChanged() {
|
||||||
|
|
|
@ -99,6 +99,14 @@ public class ConfirmationScreen extends AbstractSimiScreen {
|
||||||
textHeight = text.size() * (client.fontRenderer.FONT_HEIGHT + 1) + 4;
|
textHeight = text.size() * (client.fontRenderer.FONT_HEIGHT + 1) + 4;
|
||||||
textWidth = 300;
|
textWidth = 300;
|
||||||
|
|
||||||
|
if (centered) {
|
||||||
|
x = width/2 - textWidth/2 - 2;
|
||||||
|
y = height/2 - textHeight/2 - 16;
|
||||||
|
} else {
|
||||||
|
x = Math.max(0, x - textWidth / 2);
|
||||||
|
y = Math.max(0, y -= textHeight);
|
||||||
|
}
|
||||||
|
|
||||||
if (x + textWidth > width) {
|
if (x + textWidth > width) {
|
||||||
x = width - textWidth;
|
x = width - textWidth;
|
||||||
}
|
}
|
||||||
|
@ -107,11 +115,6 @@ public class ConfirmationScreen extends AbstractSimiScreen {
|
||||||
y = height - textHeight - 30;
|
y = height - textHeight - 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (centered) {
|
|
||||||
x = width/2 - textWidth/2 - 2;
|
|
||||||
y = height/2 - textHeight/2 - 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true);
|
TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true);
|
||||||
confirm = new BoxWidget(x + 4, y + textHeight + 2 , textWidth/2 - 10, 20)
|
confirm = new BoxWidget(x + 4, y + textHeight + 2 , textWidth/2 - 10, 20)
|
||||||
.withCallback(() -> accept(true));
|
.withCallback(() -> accept(true));
|
||||||
|
|
|
@ -108,6 +108,9 @@ public class PlacementOffset {
|
||||||
if (!isReplaceable(world))
|
if (!isReplaceable(world))
|
||||||
return ActionResultType.PASS;
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
|
||||||
ItemUseContext context = new ItemUseContext(player, hand, ray);
|
ItemUseContext context = new ItemUseContext(player, hand, ray);
|
||||||
BlockPos newPos = new BlockPos(pos);
|
BlockPos newPos = new BlockPos(pos);
|
||||||
|
|
||||||
|
@ -135,9 +138,6 @@ public class PlacementOffset {
|
||||||
|
|
||||||
player.addStat(Stats.ITEM_USED.get(blockItem));
|
player.addStat(Stats.ITEM_USED.get(blockItem));
|
||||||
|
|
||||||
if (world.isRemote)
|
|
||||||
return ActionResultType.SUCCESS;
|
|
||||||
|
|
||||||
if (player instanceof ServerPlayerEntity)
|
if (player instanceof ServerPlayerEntity)
|
||||||
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, newPos, context.getItem());
|
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, newPos, context.getItem());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue