Pondering Alone, Part II
-move some theme keys to a new ponder specific theme -move config gui to catnip -fix some client/server siding issues -move some icons to catnip/ponder -move some commands to catnip/ponder -refactor SConfigureConfigPacket and move it to catnip -add PonderPlugin to bundle all ponder extension points
This commit is contained in:
parent
bce234ec50
commit
57dc43e398
10
build.gradle
10
build.gradle
|
@ -99,6 +99,11 @@ minecraft {
|
|||
|
||||
server {
|
||||
workingDirectory project.file('run/server')
|
||||
if (inMultiModWorkspace)
|
||||
ideaModule "createmod.Create.main"
|
||||
else
|
||||
ideaModule "Create.main"
|
||||
|
||||
arg '-mixin.config=create.mixins.json'
|
||||
property 'forge.logging.console.level', 'info'
|
||||
mods {
|
||||
|
@ -124,6 +129,11 @@ minecraft {
|
|||
|
||||
data {
|
||||
workingDirectory project.file('run')
|
||||
if (inMultiModWorkspace)
|
||||
ideaModule "createmod.Create.main"
|
||||
else
|
||||
ideaModule "Create.main"
|
||||
|
||||
property 'forge.logging.markers', 'REGISTRIES,REGISTRYDUMP'
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
args '--mod', 'create', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources')
|
||||
|
|
|
@ -20,10 +20,8 @@ import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
|
|||
import com.simibubi.create.content.schematics.client.SchematicHandler;
|
||||
import com.simibubi.create.foundation.ClientResourceReloadListener;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.ponder.CreatePonderIndex;
|
||||
import com.simibubi.create.foundation.ponder.CreatePonderTag;
|
||||
import com.simibubi.create.foundation.ponder.CreatePonderPlugin;
|
||||
import com.simibubi.create.foundation.ponder.CreateSharedPonderText;
|
||||
import com.simibubi.create.foundation.ponder.PonderWorldTileFix;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.CreateContexts;
|
||||
import com.simibubi.create.foundation.render.SuperByteBufferCache;
|
||||
|
@ -31,7 +29,6 @@ import com.simibubi.create.foundation.utility.ModelSwapper;
|
|||
import com.simibubi.create.foundation.utility.ShippedResourcePacks;
|
||||
|
||||
import net.createmod.ponder.foundation.PonderIndex;
|
||||
import net.createmod.ponder.foundation.PonderWorld;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.GraphicsStatus;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -93,11 +90,7 @@ public class CreateClient {
|
|||
AllBlockPartials.init();
|
||||
AllStitchedTextures.init();
|
||||
|
||||
CreatePonderIndex.register();
|
||||
CreatePonderIndex.registerTags();
|
||||
PonderIndex.addIndex(CreatePonderIndex::register);
|
||||
PonderIndex.addIndex(CreatePonderTag::register);
|
||||
PonderWorld.onRestore(PonderWorldTileFix::fixControllerTiles);
|
||||
PonderIndex.addPlugin(new CreatePonderPlugin());
|
||||
|
||||
registerOverlays();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.simibubi.create.foundation.utility.ControlsUtil;
|
|||
import net.createmod.catnip.utility.animation.LerpedFloat;
|
||||
import net.createmod.catnip.utility.animation.LerpedFloat.Chaser;
|
||||
import net.createmod.catnip.utility.math.AngleHelper;
|
||||
import net.createmod.catnip.utility.placement.PlacementHelpers;
|
||||
import net.createmod.catnip.utility.placement.PlacementClient;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
|
@ -203,7 +203,7 @@ public class TrainHUD {
|
|||
|
||||
poseStack.translate(91, -9, 0);
|
||||
poseStack.scale(0.925f, 0.925f, 1);
|
||||
PlacementHelpers.textured(poseStack, 0, 0, 1, snappedAngle);
|
||||
PlacementClient.textured(poseStack, 0, 0, 1, snappedAngle);
|
||||
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.BakedModelWrapper;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
@ -29,8 +30,9 @@ public class BracketedKineticBlockModel extends BakedModelWrapper<BakedModel> {
|
|||
|
||||
@Override
|
||||
public IModelData getModelData(BlockAndTintGetter world, BlockPos pos, BlockState state, IModelData tileData) {
|
||||
if (VirtualEmptyModelData.is(tileData))
|
||||
if (VirtualEmptyModelData.is(tileData) || tileData.equals(EmptyModelData.INSTANCE))
|
||||
return tileData;
|
||||
|
||||
BracketedModelData data = new BracketedModelData();
|
||||
BracketedTileEntityBehaviour attachmentBehaviour =
|
||||
TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
|
||||
|
@ -42,16 +44,18 @@ public class BracketedKineticBlockModel extends BakedModelWrapper<BakedModel> {
|
|||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData data) {
|
||||
if (!VirtualEmptyModelData.is(data)) {
|
||||
if (data.hasProperty(BRACKET_PROPERTY)) {
|
||||
BracketedModelData pipeData = data.getData(BRACKET_PROPERTY);
|
||||
BakedModel bracket = pipeData.getBracket();
|
||||
if (bracket != null)
|
||||
return bracket.getQuads(state, side, rand, data);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
if (VirtualEmptyModelData.is(data) || data.equals(EmptyModelData.INSTANCE)) {
|
||||
return super.getQuads(state, side, rand, data);
|
||||
}
|
||||
return super.getQuads(state, side, rand, data);
|
||||
|
||||
if (data.hasProperty(BRACKET_PROPERTY)) {
|
||||
BracketedModelData pipeData = data.getData(BRACKET_PROPERTY);
|
||||
BakedModel bracket = pipeData.getBracket();
|
||||
if (bracket != null)
|
||||
return bracket.getQuads(state, side, rand, data);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static class BracketedModelData {
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
|||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllFluids;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.Create;
|
||||
|
@ -25,6 +26,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra
|
|||
import com.simibubi.create.content.contraptions.components.turntable.TurntableHandler;
|
||||
import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||
import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer;
|
||||
import com.simibubi.create.content.curiosities.girder.GirderWrenchBehavior;
|
||||
import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient;
|
||||
|
@ -46,7 +48,6 @@ import com.simibubi.create.content.logistics.trains.track.CurvedTrackInteraction
|
|||
import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackPlacement;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper;
|
||||
import com.simibubi.create.foundation.item.ItemDescription;
|
||||
import com.simibubi.create.foundation.item.TooltipHelper;
|
||||
|
@ -61,16 +62,18 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollVal
|
|||
import com.simibubi.create.foundation.utility.CameraAngleAnimationService;
|
||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||
|
||||
import net.createmod.catnip.config.ui.BaseConfigScreen;
|
||||
import net.createmod.catnip.config.ui.ConfigScreen;
|
||||
import net.createmod.catnip.render.DefaultSuperRenderTypeBufferImpl;
|
||||
import net.createmod.catnip.render.SuperRenderTypeBuffer;
|
||||
import net.createmod.catnip.utility.AnimationTickHolder;
|
||||
import net.createmod.catnip.utility.placement.PlacementHelpers;
|
||||
import net.createmod.catnip.utility.worldWrappers.WrappedClientWorld;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
|
@ -121,7 +124,6 @@ public class ClientEvents {
|
|||
}
|
||||
|
||||
SoundScapes.tick();
|
||||
AnimationTickHolder.tick();
|
||||
ScrollValueHandler.tick();
|
||||
|
||||
CreateClient.SCHEMATIC_SENDER.tick();
|
||||
|
@ -137,7 +139,6 @@ public class ClientEvents {
|
|||
CapabilityMinecartController.tick(world);
|
||||
CouplingPhysics.tick(world);
|
||||
|
||||
// ScreenOpener.tick();
|
||||
ServerSpeedProvider.clientTick();
|
||||
BeltConnectorHandler.tick();
|
||||
// BeltSlicer.tickHoveringInformation();
|
||||
|
@ -155,8 +156,6 @@ public class ClientEvents {
|
|||
// CollisionDebugger.tick();
|
||||
ArmInteractionPointHandler.tick();
|
||||
EjectorTargetHandler.tick();
|
||||
PlacementHelpers.tick();
|
||||
//CreateClient.OUTLINER.tickOutlines();
|
||||
ContraptionRenderDispatcher.tick(world);
|
||||
BlueprintOverlayRenderer.tick();
|
||||
ToolboxHandlerClient.clientTick();
|
||||
|
@ -188,7 +187,6 @@ public class ClientEvents {
|
|||
LevelAccessor world = event.getWorld();
|
||||
if (world.isClientSide() && world instanceof ClientLevel && !(world instanceof WrappedClientWorld)) {
|
||||
CreateClient.invalidateRenderers();
|
||||
AnimationTickHolder.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +197,6 @@ public class ClientEvents {
|
|||
return;
|
||||
CreateClient.invalidateRenderers();
|
||||
CreateClient.SOUL_PULSE_EFFECT_HANDLER.refresh();
|
||||
AnimationTickHolder.reset();
|
||||
ControlsHandler.levelUnloaded(event.getWorld());
|
||||
}
|
||||
|
||||
|
@ -219,7 +216,6 @@ public class ClientEvents {
|
|||
CarriageCouplingRenderer.renderAll(ms, buffer);
|
||||
CreateClient.SCHEMATIC_HANDLER.render(ms, buffer);
|
||||
|
||||
//CreateClient.OUTLINER.renderOutlines(ms, buffer, pt);
|
||||
buffer.draw();
|
||||
RenderSystem.enableCull();
|
||||
|
||||
|
@ -392,7 +388,15 @@ public class ClientEvents {
|
|||
.orElseThrow(() -> new IllegalStateException("Create Mod Container missing after loadCompleted"));
|
||||
createContainer.registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class,
|
||||
() -> new ConfigGuiHandler.ConfigGuiFactory(
|
||||
(mc, previousScreen) -> BaseConfigScreen.forCreate(previousScreen)));
|
||||
(mc, previousScreen) -> new BaseConfigScreen(previousScreen, Create.ID)));
|
||||
|
||||
BaseConfigScreen.setDefaultActionFor(Create.ID, base -> base
|
||||
.withTitles("Client Settings", "World Generation Settings", "Gameplay Settings")
|
||||
.withSpecs(AllConfigs.CLIENT.specification, AllConfigs.COMMON.specification, AllConfigs.SERVER.specification)
|
||||
);
|
||||
|
||||
ConfigScreen.shadowState = AllBlocks.LARGE_COGWHEEL.getDefaultState().setValue(CogWheelBlock.AXIS, Direction.Axis.Y);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
|
||||
import net.createmod.catnip.command.CatnipCommands;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
@ -32,8 +30,6 @@ public class AllCommands {
|
|||
.then(KillTrainCommand.register())
|
||||
.then(PassengerCommand.register())
|
||||
.then(CouplingCommand.register())
|
||||
.then(ConfigCommand.register())
|
||||
.then(PonderCommand.register())
|
||||
.then(CloneCommand.register())
|
||||
.then(GlueCommand.register())
|
||||
|
||||
|
@ -41,15 +37,10 @@ public class AllCommands {
|
|||
.then(util)
|
||||
);
|
||||
|
||||
createRoot.addChild(buildRedirect("u", util));
|
||||
|
||||
CommandNode<CommandSourceStack> c = dispatcher.findNode(Collections.singleton("c"));
|
||||
if (c != null)
|
||||
return;
|
||||
|
||||
dispatcher.getRoot()
|
||||
.addChild(buildRedirect("c", createRoot));
|
||||
createRoot.addChild(CatnipCommands.buildRedirect("u", util));
|
||||
|
||||
//add all of Create's commands to /c if it already exists, otherwise create the shortcut
|
||||
CatnipCommands.createOrAddToShortcut(dispatcher, "c", createRoot);
|
||||
}
|
||||
|
||||
private static LiteralCommandNode<CommandSourceStack> buildUtilityCommands() {
|
||||
|
@ -59,38 +50,9 @@ public class AllCommands {
|
|||
.then(ClearBufferCacheCommand.register())
|
||||
.then(CameraDistanceCommand.register())
|
||||
.then(CameraAngleCommand.register())
|
||||
.then(FlySpeedCommand.register())
|
||||
//.then(KillTPSCommand.register())
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* *****
|
||||
* https://github.com/VelocityPowered/Velocity/blob/8abc9c80a69158ebae0121fda78b55c865c0abad/proxy/src/main/java/com/velocitypowered/proxy/util/BrigadierUtils.java#L38
|
||||
* *****
|
||||
* <p>
|
||||
* Returns a literal node that redirects its execution to
|
||||
* the given destination node.
|
||||
*
|
||||
* @param alias the command alias
|
||||
* @param destination the destination node
|
||||
*
|
||||
* @return the built node
|
||||
*/
|
||||
public static LiteralCommandNode<CommandSourceStack> buildRedirect(final String alias, final LiteralCommandNode<CommandSourceStack> destination) {
|
||||
// Redirects only work for nodes with children, but break the top argument-less command.
|
||||
// Manually adding the root command after setting the redirect doesn't fix it.
|
||||
// See https://github.com/Mojang/brigadier/issues/46). Manually clone the node instead.
|
||||
LiteralArgumentBuilder<CommandSourceStack> builder = LiteralArgumentBuilder
|
||||
.<CommandSourceStack>literal(alias)
|
||||
.requires(destination.getRequirement())
|
||||
.forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork())
|
||||
.executes(destination.getCommand());
|
||||
for (CommandNode<CommandSourceStack> child : destination.getChildren()) {
|
||||
builder.then(child);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ import com.mojang.brigadier.arguments.FloatArgumentType;
|
|||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.CameraAngleAnimationService;
|
||||
|
||||
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
|
||||
import net.createmod.catnip.platform.CatnipServices;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class CameraAngleCommand {
|
||||
|
||||
|
@ -50,13 +50,12 @@ public class CameraAngleCommand {
|
|||
AtomicInteger targets = new AtomicInteger(0);
|
||||
|
||||
float angleTarget = FloatArgumentType.getFloat(ctx, "degrees");
|
||||
String optionName = (yaw ? SConfigureConfigPacket.Actions.camAngleYawTarget : SConfigureConfigPacket.Actions.camAnglePitchTarget).name();
|
||||
String optionName = yaw ? "camAngleYawTarget" : "camAnglePitchTarget";
|
||||
|
||||
getPlayersFromContext(ctx).forEach(player -> {
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(optionName, String.valueOf(angleTarget))
|
||||
);
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
player,
|
||||
new ClientboundSimpleActionPacket(optionName, String.valueOf(angleTarget)));
|
||||
targets.incrementAndGet();
|
||||
});
|
||||
|
||||
|
@ -67,9 +66,9 @@ public class CameraAngleCommand {
|
|||
AtomicInteger targets = new AtomicInteger(0);
|
||||
|
||||
getPlayersFromContext(ctx).forEach(player -> {
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.camAngleFunction.name(), value)
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
player,
|
||||
new ClientboundSimpleActionPacket("camAngleFunction", value)
|
||||
);
|
||||
targets.incrementAndGet();
|
||||
});
|
||||
|
@ -81,9 +80,9 @@ public class CameraAngleCommand {
|
|||
AtomicInteger targets = new AtomicInteger(0);
|
||||
|
||||
getPlayersFromContext(ctx).forEach(player -> {
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.camAngleFunction.name(), value + ":" + speed)
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
player,
|
||||
new ClientboundSimpleActionPacket("camAngleFunction", value + ":" + speed)
|
||||
);
|
||||
targets.incrementAndGet();
|
||||
});
|
||||
|
|
|
@ -3,12 +3,12 @@ package com.simibubi.create.foundation.command;
|
|||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
|
||||
import net.createmod.catnip.platform.CatnipServices;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class CameraDistanceCommand {
|
||||
|
||||
|
@ -17,10 +17,9 @@ public class CameraDistanceCommand {
|
|||
.then(Commands.literal("reset")
|
||||
.executes(ctx -> {
|
||||
ServerPlayer player = ctx.getSource().getPlayerOrException();
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.zoomMultiplier.name(), "1")
|
||||
);
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
player,
|
||||
new ClientboundSimpleActionPacket("zoomMultiplier", ""));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
})
|
||||
|
@ -28,10 +27,9 @@ public class CameraDistanceCommand {
|
|||
.executes(ctx -> {
|
||||
float multiplier = FloatArgumentType.getFloat(ctx, "multiplier");
|
||||
ServerPlayer player = ctx.getSource().getPlayerOrException();
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.zoomMultiplier.name(), String.valueOf(multiplier))
|
||||
);
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
player,
|
||||
new ClientboundSimpleActionPacket("zoomMultiplier", String.valueOf(multiplier)));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
})
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
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.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
/**
|
||||
* Examples:
|
||||
* /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 static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("config")
|
||||
.executes(ctx -> {
|
||||
ServerPlayer player = ctx.getSource().getPlayerOrException();
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.configScreen.name(), "")
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
})
|
||||
.then(Commands.argument("path", StringArgumentType.string())
|
||||
.executes(ctx -> {
|
||||
ServerPlayer player = ctx.getSource().getPlayerOrException();
|
||||
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.hasPermission(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().sendFailure(new TextComponent(e.getMessage()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (configPath.getType() == ModConfig.Type.CLIENT) {
|
||||
ServerPlayer player = ctx.getSource().getPlayerOrException();
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket("SET" + path, value)
|
||||
);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
try {
|
||||
ConfigHelper.setConfigValue(configPath, value);
|
||||
ctx.getSource().sendSuccess(new TextComponent("Great Success!"), false);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
} catch (ConfigHelper.InvalidValueException e) {
|
||||
ctx.getSource().sendFailure(new TextComponent("Config could not be set the the specified value!"));
|
||||
return 0;
|
||||
} catch (Exception e) {
|
||||
ctx.getSource().sendFailure(new TextComponent("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;
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,12 +2,12 @@ package com.simibubi.create.foundation.command;
|
|||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
|
||||
import net.createmod.catnip.platform.CatnipServices;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class FabulousWarningCommand {
|
||||
|
||||
|
@ -18,10 +18,9 @@ public class FabulousWarningCommand {
|
|||
ServerPlayer player = ctx.getSource()
|
||||
.getPlayerOrException();
|
||||
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fabulousWarning.name(), "")
|
||||
);
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
player,
|
||||
new ClientboundSimpleActionPacket("fabulousWarning", ""));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
});
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
|
||||
import net.createmod.catnip.platform.CatnipServices;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class FixLightingCommand {
|
||||
|
||||
|
@ -15,9 +14,9 @@ public class FixLightingCommand {
|
|||
return Commands.literal("fixLighting")
|
||||
.requires(cs -> cs.hasPermission(0))
|
||||
.executes(ctx -> {
|
||||
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) ctx.getSource()
|
||||
.getEntity()),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
ctx.getSource().getPlayerOrException(),
|
||||
new ClientboundSimpleActionPacket("fixLighting", String.valueOf(true)));
|
||||
|
||||
ctx.getSource()
|
||||
.sendSuccess(
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class FlySpeedCommand {
|
||||
|
||||
public static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("flySpeed")
|
||||
.requires(cs -> cs.hasPermission(2))
|
||||
.then(Commands.argument("speed", FloatArgumentType.floatArg(0))
|
||||
.then(Commands.argument("target", EntityArgument.player())
|
||||
.executes(ctx -> sendFlySpeedUpdate(ctx, EntityArgument.getPlayer(ctx, "target"),
|
||||
FloatArgumentType.getFloat(ctx, "speed"))))
|
||||
.executes(ctx -> sendFlySpeedUpdate(ctx, ctx.getSource()
|
||||
.getPlayerOrException(), FloatArgumentType.getFloat(ctx, "speed"))))
|
||||
.then(Commands.literal("reset")
|
||||
.then(Commands.argument("target", EntityArgument.player())
|
||||
.executes(ctx -> sendFlySpeedUpdate(ctx, EntityArgument.getPlayer(ctx, "target"), 0.05f)))
|
||||
.executes(ctx -> sendFlySpeedUpdate(ctx, ctx.getSource()
|
||||
.getPlayerOrException(), 0.05f))
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
private static int sendFlySpeedUpdate(CommandContext<CommandSourceStack> ctx, ServerPlayer player, float speed) {
|
||||
ClientboundPlayerAbilitiesPacket packet = new ClientboundPlayerAbilitiesPacket(player.getAbilities());
|
||||
packet.flyingSpeed = speed;
|
||||
player.connection.send(packet);
|
||||
|
||||
ctx.getSource()
|
||||
.sendSuccess(new TextComponent("Temporarily set " + player.getName()
|
||||
.getString() + "'s Flying Speed to: " + speed), true);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
|
||||
import net.createmod.catnip.platform.CatnipServices;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class OverlayConfigCommand {
|
||||
|
||||
|
@ -18,12 +19,12 @@ public class OverlayConfigCommand {
|
|||
.requires(cs -> cs.hasPermission(0))
|
||||
.then(Commands.literal("reset")
|
||||
.executes(ctx -> {
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SConfigureConfigPacket.Actions.overlayReset.performAction(""));
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SimpleCreateActions.overlayReset(""));
|
||||
|
||||
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () ->
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> (ServerPlayer) ctx.getSource().getEntity()),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.overlayReset.name(), "")));
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
(Player) ctx.getSource().getEntity(),
|
||||
new ClientboundSimpleActionPacket("overlayReset", "")));
|
||||
|
||||
ctx.getSource()
|
||||
.sendSuccess(new TextComponent("reset overlay offset"), true);
|
||||
|
@ -32,17 +33,17 @@ public class OverlayConfigCommand {
|
|||
})
|
||||
)
|
||||
.executes(ctx -> {
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SConfigureConfigPacket.Actions.overlayScreen.performAction(""));
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SimpleCreateActions.overlayScreen(""));
|
||||
|
||||
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () ->
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> (ServerPlayer) ctx.getSource().getEntity()),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.overlayScreen.name(), "")));
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
(Player) ctx.getSource().getEntity(),
|
||||
new ClientboundSimpleActionPacket("overlayScreen", "")));
|
||||
|
||||
ctx.getSource()
|
||||
.sendSuccess(new TextComponent("window opened"), true);
|
||||
|
||||
return 1;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.createmod.ponder.foundation.PonderRegistry;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.commands.arguments.ResourceLocationArgument;
|
||||
import net.minecraft.commands.synchronization.SuggestionProviders;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class PonderCommand {
|
||||
public static final SuggestionProvider<CommandSourceStack> ITEM_PONDERS = SuggestionProviders.register(new ResourceLocation("all_ponders"), (iSuggestionProviderCommandContext, builder) -> SharedSuggestionProvider.suggestResource(PonderRegistry.ALL.keySet().stream(), builder));
|
||||
|
||||
static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("ponder")
|
||||
.requires(cs -> cs.hasPermission(0))
|
||||
.executes(ctx -> openScene("index", ctx.getSource().getPlayerOrException()))
|
||||
.then(Commands.argument("scene", ResourceLocationArgument.id())
|
||||
.suggests(ITEM_PONDERS)
|
||||
.executes(ctx -> openScene(ResourceLocationArgument.getId(ctx, "scene").toString(), ctx.getSource().getPlayerOrException()))
|
||||
.then(Commands.argument("targets", EntityArgument.players())
|
||||
.requires(cs -> cs.hasPermission(2))
|
||||
.executes(ctx -> openScene(ResourceLocationArgument.getId(ctx, "scene").toString(), EntityArgument.getPlayers(ctx, "targets")))
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private static int openScene(String sceneId, ServerPlayer player) {
|
||||
return openScene(sceneId, ImmutableList.of(player));
|
||||
}
|
||||
|
||||
private static int openScene(String sceneId, Collection<? extends ServerPlayer> players) {
|
||||
for (ServerPlayer player : players) {
|
||||
if (player instanceof FakePlayer)
|
||||
continue;
|
||||
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.openPonder.name(), sceneId));
|
||||
}
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
|
@ -1,275 +0,0 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
|
||||
import com.simibubi.create.content.logistics.trains.CameraDistanceModifier;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
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.networking.SimplePacketBase;
|
||||
import com.simibubi.create.foundation.utility.CameraAngleAnimationService;
|
||||
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
import net.createmod.ponder.foundation.PonderRegistry;
|
||||
import net.createmod.ponder.foundation.ui.PonderIndexScreen;
|
||||
import net.createmod.ponder.foundation.ui.PonderUI;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.ForgeConfig;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
public class SConfigureConfigPacket extends SimplePacketBase {
|
||||
|
||||
private final String option;
|
||||
private final String value;
|
||||
|
||||
public SConfigureConfigPacket(String option, String value) {
|
||||
this.option = option;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public SConfigureConfigPacket(FriendlyByteBuf buffer) {
|
||||
this.option = buffer.readUtf(32767);
|
||||
this.value = buffer.readUtf(32767);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeUtf(option);
|
||||
buffer.writeUtf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get()
|
||||
.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
if (option.startsWith("SET")) {
|
||||
trySetConfig(option.substring(3), value);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Actions.valueOf(option)
|
||||
.performAction(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
LogManager.getLogger()
|
||||
.warn("Received ConfigureConfigPacket with invalid Option: " + option);
|
||||
}
|
||||
}));
|
||||
|
||||
ctx.get()
|
||||
.setPacketHandled(true);
|
||||
}
|
||||
|
||||
private static void trySetConfig(String option, String value) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
ConfigHelper.ConfigPath configPath;
|
||||
try {
|
||||
configPath = ConfigHelper.ConfigPath.parse(option);
|
||||
} catch (IllegalArgumentException e) {
|
||||
player.displayClientMessage(new TextComponent(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.displayClientMessage(new TextComponent("Great Success!"), false);
|
||||
} catch (ConfigHelper.InvalidValueException e) {
|
||||
player.displayClientMessage(new TextComponent("Config could not be set the the specified value!"), false);
|
||||
} catch (Exception e) {
|
||||
player.displayClientMessage(new TextComponent("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 {
|
||||
configScreen(() -> Actions::configScreen),
|
||||
rainbowDebug(() -> Actions::rainbowDebug),
|
||||
overlayScreen(() -> Actions::overlayScreen),
|
||||
fixLighting(() -> Actions::experimentalLighting),
|
||||
overlayReset(() -> Actions::overlayReset),
|
||||
openPonder(() -> Actions::openPonder),
|
||||
fabulousWarning(() -> Actions::fabulousWarning),
|
||||
zoomMultiplier(() -> Actions::zoomMultiplier),
|
||||
camAngleYawTarget(() -> value -> camAngleTarget(value, true)),
|
||||
camAnglePitchTarget(() -> value -> camAngleTarget(value, false)),
|
||||
camAngleFunction(() -> Actions::camAngleFunction)
|
||||
|
||||
;
|
||||
|
||||
private final Supplier<Consumer<String>> consumer;
|
||||
|
||||
Actions(Supplier<Consumer<String>> action) {
|
||||
this.consumer = action;
|
||||
}
|
||||
|
||||
void performAction(String value) {
|
||||
consumer.get()
|
||||
.accept(value);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void configScreen(String value) {
|
||||
if (value.equals("")) {
|
||||
ScreenOpener.open(BaseConfigScreen.forCreate(null));
|
||||
return;
|
||||
}
|
||||
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
ConfigHelper.ConfigPath configPath;
|
||||
try {
|
||||
configPath = ConfigHelper.ConfigPath.parse(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
player.displayClientMessage(new TextComponent(e.getMessage()), false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ScreenOpener.open(SubMenuConfigScreen.find(configPath));
|
||||
} catch (Exception e) {
|
||||
player.displayClientMessage(new TextComponent("Unable to find the specified config"), false);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void rainbowDebug(String value) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (player == null || "".equals(value))
|
||||
return;
|
||||
|
||||
if (value.equals("info")) {
|
||||
Component text = new TextComponent("Rainbow Debug Utility is currently: ")
|
||||
.append(boolToText(AllConfigs.CLIENT.rainbowDebug.get()));
|
||||
player.displayClientMessage(text, false);
|
||||
return;
|
||||
}
|
||||
|
||||
AllConfigs.CLIENT.rainbowDebug.set(Boolean.parseBoolean(value));
|
||||
Component text = boolToText(AllConfigs.CLIENT.rainbowDebug.get())
|
||||
.append(new TextComponent(" Rainbow Debug Utility").withStyle(ChatFormatting.WHITE));
|
||||
player.displayClientMessage(text, false);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void overlayReset(String value) {
|
||||
AllConfigs.CLIENT.overlayOffsetX.set(0);
|
||||
AllConfigs.CLIENT.overlayOffsetY.set(0);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void overlayScreen(String value) {
|
||||
ScreenOpener.open(new GoggleConfigScreen());
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void experimentalLighting(String value) {
|
||||
ForgeConfig.CLIENT.experimentalForgeLightPipelineEnabled.set(true);
|
||||
Minecraft.getInstance().levelRenderer.allChanged();
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void openPonder(String value) {
|
||||
if (value.equals("index")) {
|
||||
ScreenOpener.transitionTo(new PonderIndexScreen());
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceLocation id = new ResourceLocation(value);
|
||||
if (!PonderRegistry.ALL.containsKey(id)) {
|
||||
Create.LOGGER.error("Could not find ponder scenes for item: " + id);
|
||||
return;
|
||||
}
|
||||
|
||||
ScreenOpener.transitionTo(PonderUI.of(id));
|
||||
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void fabulousWarning(String value) {
|
||||
AllConfigs.CLIENT.ignoreFabulousWarning.set(true);
|
||||
Minecraft.getInstance().gui.handleChat(ChatType.CHAT,
|
||||
new TextComponent("Disabled Fabulous graphics warning"),
|
||||
Minecraft.getInstance().player.getUUID());
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void zoomMultiplier(String value) {
|
||||
try {
|
||||
float v = Float.parseFloat(value);
|
||||
if (v <= 0)
|
||||
return;
|
||||
|
||||
CameraDistanceModifier.zoomOut(v);
|
||||
} catch (NumberFormatException ignored) {
|
||||
Create.LOGGER.debug("Received non-float value {} in zoom packet, ignoring", value);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void camAngleTarget(String value, boolean yaw) {
|
||||
try {
|
||||
float v = Float.parseFloat(value);
|
||||
|
||||
if (yaw) {
|
||||
CameraAngleAnimationService.setYawTarget(v);
|
||||
} else {
|
||||
CameraAngleAnimationService.setPitchTarget(v);
|
||||
}
|
||||
|
||||
} catch (NumberFormatException ignored) {
|
||||
Create.LOGGER.debug("Received non-float value {} in camAngle packet, ignoring", value);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void camAngleFunction(String value) {
|
||||
CameraAngleAnimationService.Mode mode = CameraAngleAnimationService.Mode.LINEAR;
|
||||
String modeString = value;
|
||||
float speed = -1;
|
||||
String[] split = value.split(":");
|
||||
if (split.length > 1) {
|
||||
modeString = split[0];
|
||||
try {
|
||||
speed = Float.parseFloat(split[1]);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
try {
|
||||
mode = CameraAngleAnimationService.Mode.valueOf(modeString);
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
|
||||
CameraAngleAnimationService.setAnimationMode(mode);
|
||||
CameraAngleAnimationService.setAnimationSpeed(speed);
|
||||
}
|
||||
|
||||
private static MutableComponent boolToText(boolean b) {
|
||||
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN)
|
||||
: new TextComponent("disabled").withStyle(ChatFormatting.RED);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
|
||||
import com.simibubi.create.content.logistics.trains.CameraDistanceModifier;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.utility.CameraAngleAnimationService;
|
||||
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraftforge.common.ForgeConfig;
|
||||
|
||||
public class SimpleCreateActions {
|
||||
|
||||
public static void rainbowDebug(String value) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (player == null || "".equals(value))
|
||||
return;
|
||||
|
||||
if (value.equals("info")) {
|
||||
Component text = new TextComponent("Rainbow Debug Utility is currently: ")
|
||||
.append(boolToText(AllConfigs.CLIENT.rainbowDebug.get()));
|
||||
player.displayClientMessage(text, false);
|
||||
return;
|
||||
}
|
||||
|
||||
AllConfigs.CLIENT.rainbowDebug.set(Boolean.parseBoolean(value));
|
||||
Component text = boolToText(AllConfigs.CLIENT.rainbowDebug.get())
|
||||
.append(new TextComponent(" Rainbow Debug Utility").withStyle(ChatFormatting.WHITE));
|
||||
player.displayClientMessage(text, false);
|
||||
}
|
||||
|
||||
public static void overlayReset(String value) {
|
||||
AllConfigs.CLIENT.overlayOffsetX.set(0);
|
||||
AllConfigs.CLIENT.overlayOffsetY.set(0);
|
||||
}
|
||||
|
||||
public static void overlayScreen(String value) {
|
||||
ScreenOpener.open(new GoggleConfigScreen());
|
||||
}
|
||||
|
||||
public static void experimentalLighting(String value) {
|
||||
ForgeConfig.CLIENT.experimentalForgeLightPipelineEnabled.set(true);
|
||||
Minecraft.getInstance().levelRenderer.allChanged();
|
||||
}
|
||||
|
||||
public static void fabulousWarning(String value) {
|
||||
AllConfigs.CLIENT.ignoreFabulousWarning.set(true);
|
||||
Minecraft.getInstance().gui.handleChat(ChatType.CHAT,
|
||||
new TextComponent("Disabled Fabulous graphics warning"),
|
||||
Minecraft.getInstance().player.getUUID());
|
||||
}
|
||||
|
||||
public static void zoomMultiplier(String value) {
|
||||
try {
|
||||
float v = Float.parseFloat(value);
|
||||
if (v <= 0)
|
||||
return;
|
||||
|
||||
CameraDistanceModifier.zoomOut(v);
|
||||
} catch (NumberFormatException ignored) {
|
||||
Create.LOGGER.debug("Received non-float value {} in zoom packet, ignoring", value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void camAngleTarget(String value, boolean yaw) {
|
||||
try {
|
||||
float v = Float.parseFloat(value);
|
||||
|
||||
if (yaw) {
|
||||
CameraAngleAnimationService.setYawTarget(v);
|
||||
} else {
|
||||
CameraAngleAnimationService.setPitchTarget(v);
|
||||
}
|
||||
|
||||
} catch (NumberFormatException ignored) {
|
||||
Create.LOGGER.debug("Received non-float value {} in camAngle packet, ignoring", value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void camAngleFunction(String value) {
|
||||
CameraAngleAnimationService.Mode mode = CameraAngleAnimationService.Mode.LINEAR;
|
||||
String modeString = value;
|
||||
float speed = -1;
|
||||
String[] split = value.split(":");
|
||||
if (split.length > 1) {
|
||||
modeString = split[0];
|
||||
try {
|
||||
speed = Float.parseFloat(split[1]);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
try {
|
||||
mode = CameraAngleAnimationService.Mode.valueOf(modeString);
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
|
||||
CameraAngleAnimationService.setAnimationMode(mode);
|
||||
CameraAngleAnimationService.setAnimationSpeed(speed);
|
||||
}
|
||||
|
||||
private static MutableComponent boolToText(boolean b) {
|
||||
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN)
|
||||
: new TextComponent("disabled").withStyle(ChatFormatting.RED);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
package com.simibubi.create.foundation.command;
|
||||
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
|
||||
import net.createmod.catnip.platform.CatnipServices;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
||||
public class ToggleDebugCommand extends ConfigureConfigCommand {
|
||||
|
||||
|
@ -13,9 +12,9 @@ public class ToggleDebugCommand extends ConfigureConfigCommand {
|
|||
|
||||
@Override
|
||||
protected void sendPacket(ServerPlayer player, String option) {
|
||||
AllPackets.channel.send(
|
||||
PacketDistributor.PLAYER.with(() -> player),
|
||||
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.rainbowDebug.name(), option)
|
||||
CatnipServices.NETWORK.sendToPlayer(
|
||||
player,
|
||||
new ClientboundSimpleActionPacket("rainbowDebug", option)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,8 @@ package com.simibubi.create.foundation.config;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.simibubi.create.foundation.config.ui.ConfigAnnotations;
|
||||
|
||||
import net.createmod.catnip.config.ConfigBase;
|
||||
import net.createmod.catnip.config.ui.ConfigAnnotations;
|
||||
|
||||
public class CClient extends ConfigBase {
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package com.simibubi.create.foundation.config;
|
||||
|
||||
import com.simibubi.create.foundation.config.ui.ConfigAnnotations;
|
||||
|
||||
import net.createmod.catnip.config.ConfigBase;
|
||||
import net.createmod.catnip.config.ui.ConfigAnnotations;
|
||||
|
||||
public class CKinetics extends ConfigBase {
|
||||
|
||||
|
|
|
@ -1,252 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
|
||||
import net.createmod.catnip.gui.element.FadableScreenElement;
|
||||
import net.createmod.catnip.utility.FontHelper;
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.createmod.catnip.gui.UIRenderHelper;
|
||||
import net.createmod.catnip.gui.element.TextStencilElement;
|
||||
import net.createmod.catnip.gui.widget.BoxWidget;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
public class BaseConfigScreen extends ConfigScreen {
|
||||
|
||||
public static final FadableScreenElement DISABLED_RENDERER = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.Key.BUTTON_DISABLE.p());
|
||||
private static final Map<String, UnaryOperator<BaseConfigScreen>> DEFAULTS = new HashMap<>();
|
||||
|
||||
static {
|
||||
DEFAULTS.put(Create.ID, (base) -> base
|
||||
.withTitles("Client Settings", "World Generation Settings", "Gameplay Settings")
|
||||
.withSpecs(AllConfigs.CLIENT.specification, AllConfigs.COMMON.specification, AllConfigs.SERVER.specification)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If you are a Create Addon dev and want to change the config labels,
|
||||
* add a default action here.
|
||||
*
|
||||
* Make sure you call either {@link #withSpecs(ForgeConfigSpec, ForgeConfigSpec, ForgeConfigSpec)}
|
||||
* or {@link #searchForSpecsInModContainer()}
|
||||
*
|
||||
* @param modID the modID of your addon/mod
|
||||
*/
|
||||
public static void setDefaultActionFor(String modID, UnaryOperator<BaseConfigScreen> transform) {
|
||||
if (modID.equals(Create.ID))
|
||||
return;
|
||||
|
||||
DEFAULTS.put(modID, transform);
|
||||
}
|
||||
|
||||
public static BaseConfigScreen forCreate(Screen parent) {
|
||||
return new BaseConfigScreen(parent);
|
||||
}
|
||||
|
||||
BoxWidget clientConfigWidget;
|
||||
BoxWidget commonConfigWidget;
|
||||
BoxWidget serverConfigWidget;
|
||||
BoxWidget goBack;
|
||||
BoxWidget others;
|
||||
BoxWidget title;
|
||||
|
||||
ForgeConfigSpec clientSpec;
|
||||
ForgeConfigSpec commonSpec;
|
||||
ForgeConfigSpec serverSpec;
|
||||
String clientTile = "Client Config";
|
||||
String commonTile = "Common Config";
|
||||
String serverTile = "Server Config";
|
||||
String modID;
|
||||
protected boolean returnOnClose;
|
||||
|
||||
public BaseConfigScreen(Screen parent, @Nonnull String modID) {
|
||||
super(parent);
|
||||
this.modID = modID;
|
||||
|
||||
if (DEFAULTS.containsKey(modID))
|
||||
DEFAULTS.get(modID).apply(this);
|
||||
else {
|
||||
this.searchForSpecsInModContainer();
|
||||
}
|
||||
}
|
||||
|
||||
private BaseConfigScreen(Screen parent) {
|
||||
this(parent, Create.ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
if (!ConfigHelper.hasAnyForgeConfig(this.modID)){
|
||||
return this;
|
||||
}
|
||||
|
||||
try {
|
||||
clientSpec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.CLIENT, this.modID);
|
||||
} catch (Exception e) {
|
||||
Create.LOGGER.debug("Unable to find ClientConfigSpec for mod: " + this.modID);
|
||||
}
|
||||
|
||||
try {
|
||||
commonSpec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.COMMON, this.modID);
|
||||
} catch (Exception e) {
|
||||
Create.LOGGER.debug("Unable to find CommonConfigSpec for mod: " + this.modID);
|
||||
}
|
||||
|
||||
try {
|
||||
serverSpec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.SERVER, this.modID);
|
||||
} catch (Exception e) {
|
||||
Create.LOGGER.debug("Unable to find ServerConfigSpec for mod: " + this.modID);
|
||||
}
|
||||
|
||||
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
|
||||
protected void init() {
|
||||
super.init();
|
||||
returnOnClose = true;
|
||||
|
||||
TextStencilElement clientText = new TextStencilElement(font, new TextComponent(clientTile)).centered(true, true);
|
||||
addRenderableWidget(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16).showingElement(clientText));
|
||||
|
||||
if (clientSpec != null) {
|
||||
clientConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, clientSpec)));
|
||||
clientText.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget));
|
||||
} else {
|
||||
clientConfigWidget.active = false;
|
||||
clientConfigWidget.updateColorsFromState();
|
||||
clientText.withElementRenderer(DISABLED_RENDERER);
|
||||
}
|
||||
|
||||
TextStencilElement commonText = new TextStencilElement(font, new TextComponent(commonTile)).centered(true, true);
|
||||
addRenderableWidget(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16).showingElement(commonText));
|
||||
|
||||
if (commonSpec != null) {
|
||||
commonConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, commonSpec)));
|
||||
commonText.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget));
|
||||
} else {
|
||||
commonConfigWidget.active = false;
|
||||
commonConfigWidget.updateColorsFromState();
|
||||
commonText.withElementRenderer(DISABLED_RENDERER);
|
||||
}
|
||||
|
||||
TextStencilElement serverText = new TextStencilElement(font, new TextComponent(serverTile)).centered(true, true);
|
||||
addRenderableWidget(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16).showingElement(serverText));
|
||||
|
||||
if (serverSpec == null) {
|
||||
serverConfigWidget.active = false;
|
||||
serverConfigWidget.updateColorsFromState();
|
||||
serverText.withElementRenderer(DISABLED_RENDERER);
|
||||
} else if (minecraft.level == null) {
|
||||
serverText.withElementRenderer(DISABLED_RENDERER);
|
||||
serverConfigWidget.getToolTip()
|
||||
.add(new TextComponent("Stored individually per World"));
|
||||
serverConfigWidget.getToolTip()
|
||||
.addAll(FontHelper.cutTextComponent(
|
||||
new TextComponent(
|
||||
"Gameplay settings can only be accessed from the in-game menu after joining a World or Server."),
|
||||
ChatFormatting.GRAY, ChatFormatting.GRAY));
|
||||
} else {
|
||||
serverConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, serverSpec)));
|
||||
serverText.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget));
|
||||
}
|
||||
|
||||
TextStencilElement titleText = new TextStencilElement(font, modID.toUpperCase(Locale.ROOT))
|
||||
.centered(true, true)
|
||||
.withElementRenderer((ms, w, h, alpha) -> {
|
||||
UIRenderHelper.angledGradient(ms, 0, 0, h / 2, h, w / 2, Theme.Key.CONFIG_TITLE_A.p());
|
||||
UIRenderHelper.angledGradient(ms, 0, w / 2, h / 2, h, w / 2, Theme.Key.CONFIG_TITLE_B.p());
|
||||
});
|
||||
int boxWidth = width + 10;
|
||||
int boxHeight = 39;
|
||||
int boxPadding = 4;
|
||||
title = new BoxWidget(-5, height / 2 - 110, boxWidth, boxHeight)
|
||||
//.withCustomBackground(new Color(0x20_000000, true))
|
||||
.withBorderColors(Theme.Key.BUTTON_IDLE.p())
|
||||
.withPadding(0, boxPadding)
|
||||
.rescaleElement(boxWidth / 2f, (boxHeight - 2 * boxPadding) / 2f)//double the text size by telling it the element is only half as big as the available space
|
||||
.showingElement(titleText.at(0, 7));
|
||||
title.active = false;
|
||||
|
||||
addRenderableWidget(title);
|
||||
|
||||
|
||||
ConfigScreen.modID = this.modID;
|
||||
|
||||
goBack = new BoxWidget(width / 2 - 134, height / 2, 20, 20).withPadding(2, 2)
|
||||
.withCallback(() -> linkTo(parent));
|
||||
goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil()
|
||||
.withElementRenderer(BoxWidget.gradientFactory.apply(goBack)));
|
||||
goBack.getToolTip()
|
||||
.add(new TextComponent("Go Back"));
|
||||
addRenderableWidget(goBack);
|
||||
|
||||
TextStencilElement othersText = new TextStencilElement(font, new TextComponent("Access Configs of other Mods")).centered(true, true);
|
||||
others = new BoxWidget(width / 2 - 100, height / 2 - 15 + 90, 200, 16).showingElement(othersText);
|
||||
othersText.withElementRenderer(BoxWidget.gradientFactory.apply(others));
|
||||
others.withCallback(() -> linkTo(new ConfigModListScreen(this)));
|
||||
addRenderableWidget(others);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
drawCenteredString(ms, font, "Access Configs for Mod:", width / 2, height / 2 - 105, Theme.Key.TEXT_ACCENT_STRONG.i());
|
||||
}
|
||||
|
||||
private void linkTo(Screen screen) {
|
||||
returnOnClose = false;
|
||||
ScreenOpener.open(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (super.keyPressed(keyCode, scanCode, modifiers))
|
||||
return true;
|
||||
if (keyCode == GLFW.GLFW_KEY_BACKSPACE) {
|
||||
linkTo(parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
public class CConfigureConfigPacket<T> extends SimplePacketBase {
|
||||
|
||||
private String modID;
|
||||
private String path;
|
||||
private String value;
|
||||
|
||||
public CConfigureConfigPacket(String modID, String path, T value) {
|
||||
this.modID = Objects.requireNonNull(modID);
|
||||
this.path = path;
|
||||
this.value = serialize(value);
|
||||
}
|
||||
|
||||
public CConfigureConfigPacket(FriendlyByteBuf buffer) {
|
||||
this.modID = buffer.readUtf(32767);
|
||||
this.path = buffer.readUtf(32767);
|
||||
this.value = buffer.readUtf(32767);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeUtf(modID);
|
||||
buffer.writeUtf(path);
|
||||
buffer.writeUtf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().enqueueWork(() -> {
|
||||
try {
|
||||
ServerPlayer sender = context.get().getSender();
|
||||
if (sender == null || !sender.hasPermissions(2))
|
||||
return;
|
||||
|
||||
ForgeConfigSpec spec = ConfigHelper.findForgeConfigSpecFor(ModConfig.Type.SERVER, modID);
|
||||
if (spec == null)
|
||||
return;
|
||||
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(path);
|
||||
ForgeConfigSpec.ConfigValue<T> configValue = spec.getValues().get(path);
|
||||
|
||||
T v = (T) deserialize(configValue.get(), value);
|
||||
if (!valueSpec.test(v))
|
||||
return;
|
||||
|
||||
configValue.set(v);
|
||||
} catch (Exception e) {
|
||||
Create.LOGGER.warn("Unable to handle ConfigureConfig Packet. ", e);
|
||||
}
|
||||
});
|
||||
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
public String serialize(T value) {
|
||||
if (value instanceof Boolean)
|
||||
return Boolean.toString((Boolean) value);
|
||||
if (value instanceof Enum<?>)
|
||||
return ((Enum<?>) value).name();
|
||||
if (value instanceof Integer)
|
||||
return Integer.toString((Integer) value);
|
||||
if (value instanceof Float)
|
||||
return Float.toString((Float) value);
|
||||
if (value instanceof Double)
|
||||
return Double.toString((Double) value);
|
||||
|
||||
throw new IllegalArgumentException("unknown type " + value + ": " + value.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
public static Object deserialize(Object type, String sValue) {
|
||||
if (type instanceof Boolean)
|
||||
return Boolean.parseBoolean(sValue);
|
||||
if (type instanceof Enum<?>)
|
||||
return Enum.valueOf(((Enum<?>) type).getClass(), sValue);
|
||||
if (type instanceof Integer)
|
||||
return Integer.parseInt(sValue);
|
||||
if (type instanceof Float)
|
||||
return Float.parseFloat(sValue);
|
||||
if (type instanceof Double)
|
||||
return Double.parseDouble(sValue);
|
||||
|
||||
throw new IllegalArgumentException("unknown type " + type + ": " + type.getClass().getSimpleName());
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
public class ConfigAnnotations {
|
||||
|
||||
|
||||
/**
|
||||
* Changes the way the Integer value is display.
|
||||
*/
|
||||
public enum IntDisplay implements ConfigAnnotation {
|
||||
HEX("#"),
|
||||
ZERO_X("0x"),
|
||||
ZERO_B("0b");
|
||||
|
||||
private final String value;
|
||||
|
||||
IntDisplay(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "IntDisplay";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates to the player that changing this value will require a restart to take full effect
|
||||
*/
|
||||
public enum RequiresRestart implements ConfigAnnotation {
|
||||
CLIENT("client"),
|
||||
SERVER("server"),
|
||||
BOTH("both");
|
||||
|
||||
private final String value;
|
||||
|
||||
RequiresRestart(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "RequiresReload";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates to the player that changing this value will require them to relog to take full effect
|
||||
*/
|
||||
public enum RequiresRelog implements ConfigAnnotation {
|
||||
TRUE;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "RequiresRelog";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changing a value that is annotated with Execute will cause the player to run the given command automatically.
|
||||
*/
|
||||
public static class Execute implements ConfigAnnotation {
|
||||
|
||||
private final String command;
|
||||
|
||||
public static Execute run(String command) {
|
||||
return new Execute(command);
|
||||
}
|
||||
|
||||
private Execute(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Execute";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ConfigAnnotation {
|
||||
String getName();
|
||||
|
||||
default String getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default String asComment() {
|
||||
String comment = "[@cui:" + getName();
|
||||
String value = getValue();
|
||||
if (value != null) {
|
||||
comment = comment + ":" + value;
|
||||
}
|
||||
comment = comment + "]";
|
||||
return comment;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
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.createmod.catnip.utility.Pair;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.config.IConfigSpec;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
|
||||
public class ConfigHelper {
|
||||
|
||||
public static final Pattern unitPattern = Pattern.compile("\\[(in .*)]");
|
||||
public static final Pattern annotationPattern = Pattern.compile("\\[@cui:([^:]*)(?::(.*))?]");
|
||||
|
||||
public static final Map<String, ConfigChange> changes = new HashMap<>();
|
||||
private static final LoadingCache<String, EnumMap<ModConfig.Type, ModConfig>> configCache =
|
||||
CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(5, TimeUnit.MINUTES)
|
||||
.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 IConfigSpec<?> findConfigSpecFor(ModConfig.Type type, String modID) {
|
||||
if (!modID.equals(Create.ID))
|
||||
return configCache.getUnchecked(modID)
|
||||
.get(type)
|
||||
.getSpec();
|
||||
return AllConfigs.byType(type).specification;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ForgeConfigSpec findForgeConfigSpecFor(ModConfig.Type type, String modID) {
|
||||
IConfigSpec<?> spec = findConfigSpecFor(type, modID);
|
||||
if (spec instanceof ForgeConfigSpec) {
|
||||
return (ForgeConfigSpec) spec;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean hasAnyConfig(String modID) {
|
||||
if (!modID.equals(Create.ID))
|
||||
return !configCache.getUnchecked(modID)
|
||||
.isEmpty();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean hasAnyForgeConfig(String modID) {
|
||||
if (!modID.equals(Create.ID))
|
||||
return configCache.getUnchecked(modID)
|
||||
.values()
|
||||
.stream()
|
||||
.anyMatch(config -> config.getSpec() instanceof ForgeConfigSpec);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Directly set a value
|
||||
public static <T> void setConfigValue(ConfigPath path, String value) throws InvalidValueException {
|
||||
ForgeConfigSpec spec = findForgeConfigSpecFor(path.getType(), path.getModID());
|
||||
if (spec == null)
|
||||
return;
|
||||
|
||||
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,
|
||||
@Nullable Map<String, String> annotations) {
|
||||
if (value.equals(configValue.get())) {
|
||||
changes.remove(path);
|
||||
} else {
|
||||
changes.put(path, annotations == null ? new ConfigChange(value) : new ConfigChange(value, annotations));
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
ConfigChange configChange = changes.get(path);
|
||||
if (configChange != null)
|
||||
// noinspection unchecked
|
||||
return (T) configChange.value;
|
||||
else
|
||||
return configValue.get();
|
||||
}
|
||||
|
||||
public static Pair<String, Map<String, String>> readMetadataFromComment(List<String> commentLines) {
|
||||
AtomicReference<String> unit = new AtomicReference<>();
|
||||
Map<String, String> annotations = new HashMap<>();
|
||||
|
||||
commentLines.removeIf(line -> {
|
||||
if (line.trim()
|
||||
.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Matcher matcher = annotationPattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
String annotation = matcher.group(1);
|
||||
String aValue = matcher.group(2);
|
||||
annotations.putIfAbsent(annotation, aValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
matcher = unitPattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
unit.set(matcher.group(1));
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return Pair.of(unit.get(), annotations);
|
||||
}
|
||||
|
||||
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 ConfigChange {
|
||||
Object value;
|
||||
Map<String, String> annotations;
|
||||
|
||||
ConfigChange(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
ConfigChange(Object value, Map<String, String> annotations) {
|
||||
this(value);
|
||||
this.annotations = new HashMap<>();
|
||||
this.annotations.putAll(annotations);
|
||||
}
|
||||
}
|
||||
|
||||
public static class InvalidValueException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
import net.createmod.catnip.gui.element.DelegatedStencilElement;
|
||||
import net.createmod.catnip.gui.widget.BoxWidget;
|
||||
import net.createmod.catnip.utility.FontHelper;
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
||||
public class ConfigModListScreen extends ConfigScreen {
|
||||
|
||||
ConfigScreenList list;
|
||||
HintableTextFieldWidget search;
|
||||
BoxWidget goBack;
|
||||
List<ModEntry> allEntries;
|
||||
|
||||
public ConfigModListScreen(Screen parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
int listWidth = Math.min(width - 80, 300);
|
||||
|
||||
list = new ConfigScreenList(minecraft, listWidth, height - 60, 15, height - 45, 40);
|
||||
list.setLeftPos(this.width / 2 - list.getWidth() / 2);
|
||||
addRenderableWidget(list);
|
||||
|
||||
allEntries = new ArrayList<>();
|
||||
ModList.get().getMods().stream().map(IModInfo::getModId).forEach(id -> allEntries.add(new ModEntry(id, this)));
|
||||
allEntries.sort((e1, e2) -> {
|
||||
int empty = (e2.button.active ? 1 : 0) - (e1.button.active ? 1 : 0);
|
||||
if (empty != 0)
|
||||
return empty;
|
||||
|
||||
return e1.id.compareToIgnoreCase(e2.id);
|
||||
});
|
||||
list.children().clear();
|
||||
list.children().addAll(allEntries);
|
||||
|
||||
goBack = new BoxWidget(width / 2 - listWidth / 2 - 30, height / 2 + 65, 20, 20).withPadding(2, 2)
|
||||
.withCallback(() -> ScreenOpener.open(parent));
|
||||
goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil()
|
||||
.withElementRenderer(BoxWidget.gradientFactory.apply(goBack)));
|
||||
goBack.getToolTip()
|
||||
.add(new TextComponent("Go Back"));
|
||||
addRenderableWidget(goBack);
|
||||
|
||||
search = new HintableTextFieldWidget(font, width / 2 - listWidth / 2, height - 35, listWidth, 20);
|
||||
search.setResponder(this::updateFilter);
|
||||
search.setHint("Search...");
|
||||
search.moveCursorToStart();
|
||||
addRenderableWidget(search);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (super.keyPressed(keyCode, scanCode, modifiers))
|
||||
return true;
|
||||
if (keyCode == GLFW.GLFW_KEY_BACKSPACE) {
|
||||
ScreenOpener.open(parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateFilter(String search) {
|
||||
list.children().clear();
|
||||
allEntries
|
||||
.stream()
|
||||
.filter(modEntry -> modEntry.id.contains(search.toLowerCase(Locale.ROOT)))
|
||||
.forEach(list.children()::add);
|
||||
|
||||
list.setScrollAmount(list.getScrollAmount());
|
||||
if (list.children().size() > 0) {
|
||||
this.search.setTextColor(Theme.Key.TEXT.i());
|
||||
} else {
|
||||
this.search.setTextColor(Theme.Key.BUTTON_FAIL.i());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModEntry extends ConfigScreenList.LabeledEntry {
|
||||
|
||||
protected BoxWidget button;
|
||||
protected String id;
|
||||
|
||||
public ModEntry(String id, Screen parent) {
|
||||
super(toHumanReadable(id));
|
||||
this.id = id;
|
||||
|
||||
button = new BoxWidget(0, 0, 35, 16)
|
||||
.showingElement(AllIcons.I_CONFIG_OPEN.asStencil().at(10, 0));
|
||||
button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(button)));
|
||||
|
||||
if (ConfigHelper.hasAnyForgeConfig(id)) {
|
||||
button.withCallback(() -> ScreenOpener.open(new BaseConfigScreen(parent, id)));
|
||||
} else {
|
||||
button.active = false;
|
||||
button.updateColorsFromState();
|
||||
button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BaseConfigScreen.DISABLED_RENDERER));
|
||||
labelTooltip.add(new TextComponent(toHumanReadable(id)));
|
||||
labelTooltip.addAll(FontHelper.cutTextComponent(new TextComponent("This Mod does not have any configs registered or is not using Forge's config system"), ChatFormatting.GRAY, ChatFormatting.GRAY));
|
||||
}
|
||||
|
||||
listeners.add(button);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
button.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
|
||||
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
|
||||
|
||||
button.x = x + width - 108;
|
||||
button.y = y + 10;
|
||||
button.setHeight(height - 20);
|
||||
button.render(ms, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLabelWidth(int totalWidth) {
|
||||
return (int) (totalWidth * labelWidthMult) + 30;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.util.TriConsumer;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||
import com.simibubi.create.foundation.gui.CreateMainMenuScreen;
|
||||
|
||||
import net.createmod.catnip.gui.AbstractSimiScreen;
|
||||
import net.createmod.catnip.gui.UIRenderHelper;
|
||||
import net.createmod.catnip.gui.element.DelegatedStencilElement;
|
||||
import net.createmod.catnip.gui.element.GuiGameElement;
|
||||
import net.createmod.catnip.utility.animation.Force;
|
||||
import net.createmod.catnip.utility.animation.PhysicalFloat;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.event.ScreenEvent;
|
||||
|
||||
public abstract class ConfigScreen extends AbstractSimiScreen {
|
||||
|
||||
/*
|
||||
*
|
||||
* TODO
|
||||
*
|
||||
* reduce number of packets sent to the server when saving a bunch of values
|
||||
*
|
||||
* FIXME
|
||||
*
|
||||
* tooltips are hidden underneath the scrollbar, if the bar is near the middle
|
||||
*
|
||||
*/
|
||||
|
||||
public static final Map<String, TriConsumer<Screen, PoseStack, Float>> backgrounds = new HashMap<>();
|
||||
public static final PhysicalFloat cogSpin = PhysicalFloat.create().withLimit(10f).withDrag(0.3).addForce(new Force.Static(.2f));
|
||||
public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().setValue(CogWheelBlock.AXIS, Direction.Axis.Y);
|
||||
public static String modID = null;
|
||||
protected final Screen parent;
|
||||
|
||||
public ConfigScreen(Screen parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
cogSpin.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderBackground(@Nonnull PoseStack ms) {
|
||||
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new ScreenEvent.BackgroundDrawnEvent(this, ms));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindowBackground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
if (this.minecraft != null && this.minecraft.level != null) {
|
||||
//in game
|
||||
fill(ms, 0, 0, this.width, this.height, 0xb0_282c34);
|
||||
} else {
|
||||
//in menus
|
||||
renderMenuBackground(ms, partialTicks);
|
||||
}
|
||||
|
||||
/*new StencilElement() {
|
||||
@Override
|
||||
protected void renderStencil(PoseStack ms) {
|
||||
renderCog(ms, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderElement(PoseStack ms) {
|
||||
fill(ms, -200, -200, 200, 200, 0x60_000000);
|
||||
}
|
||||
}*/
|
||||
|
||||
new DelegatedStencilElement(
|
||||
(ps, x, y, alpha) -> renderCog(ps, partialTicks),
|
||||
(ps, x, y, alpha) -> fill(ms, -200, -200, 200, 200, 0x60_000000)
|
||||
).at(width * 0.5f, height * 0.5f, 0).render(ms);
|
||||
|
||||
super.renderWindowBackground(ms, mouseX, mouseY, partialTicks);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareFrame() {
|
||||
UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer);
|
||||
RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void endFrame() {
|
||||
UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
|
||||
cogSpin.bump(3, -delta * 5);
|
||||
|
||||
return super.mouseScrolled(mouseX, mouseY, delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String toHumanReadable(String key) {
|
||||
String s = key.replaceAll("_", " ");
|
||||
s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(s)).map(StringUtils::capitalize).collect(Collectors.joining(" "));
|
||||
s = StringUtils.normalizeSpace(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default ConfigScreens will render the Create Panorama as
|
||||
* their background when opened from the Main- or ModList-Menu.
|
||||
* If your addon wants to render something else, please add to the
|
||||
* backgrounds Map in this Class with your modID as the key.
|
||||
*/
|
||||
protected void renderMenuBackground(PoseStack ms, float partialTicks) {
|
||||
TriConsumer<Screen, PoseStack, Float> customBackground = backgrounds.get(modID);
|
||||
if (customBackground != null) {
|
||||
customBackground.accept(this, ms, partialTicks);
|
||||
return;
|
||||
}
|
||||
|
||||
float elapsedPartials = minecraft.getDeltaFrameTime();
|
||||
CreateMainMenuScreen.PANORAMA.render(elapsedPartials, 1);
|
||||
|
||||
RenderSystem.setShaderTexture(0, CreateMainMenuScreen.PANORAMA_OVERLAY_TEXTURES);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
blit(ms, 0, 0, this.width, this.height, 0.0F, 0.0F, 16, 128, 16, 128);
|
||||
|
||||
fill(ms, 0, 0, this.width, this.height, 0x90_282c34);
|
||||
}
|
||||
|
||||
protected void renderCog(PoseStack ms, float partialTicks) {
|
||||
ms.pushPose();
|
||||
|
||||
ms.translate(-100, 100, -100);
|
||||
ms.scale(200, 200, 1);
|
||||
GuiGameElement.of(cogwheelState)
|
||||
.rotateBlock(22.5, cogSpin.getValue(partialTicks), 22.5)
|
||||
.render(ms);
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
}
|
|
@ -1,278 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
|
||||
import com.simibubi.create.foundation.gui.RemovedGuiUtils;
|
||||
|
||||
import net.createmod.catnip.gui.TickableGuiEventListener;
|
||||
import net.createmod.catnip.gui.UIRenderHelper;
|
||||
import net.createmod.catnip.gui.element.TextStencilElement;
|
||||
import net.createmod.catnip.utility.animation.LerpedFloat;
|
||||
import net.createmod.catnip.utility.theme.Color;
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.ObjectSelectionList;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
public class ConfigScreenList extends ObjectSelectionList<ConfigScreenList.Entry> implements TickableGuiEventListener {
|
||||
|
||||
public static EditBox currentText;
|
||||
|
||||
public ConfigScreenList(Minecraft client, int width, int height, int top, int bottom, int elementHeight) {
|
||||
super(client, width, height, top, bottom, elementHeight);
|
||||
setRenderBackground(false);
|
||||
setRenderTopAndBottom(false);
|
||||
setRenderSelection(false);
|
||||
currentText = null;
|
||||
headerHeight = 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
Color c = new Color(0x60_000000);
|
||||
UIRenderHelper.angledGradient(ms, 90, x0 + width / 2, y0, width, 5, c, Color.TRANSPARENT_BLACK);
|
||||
UIRenderHelper.angledGradient(ms, -90, x0 + width / 2, y1, width, 5, c, Color.TRANSPARENT_BLACK);
|
||||
UIRenderHelper.angledGradient(ms, 0, x0, y0 + height / 2, height, 5, c, Color.TRANSPARENT_BLACK);
|
||||
UIRenderHelper.angledGradient(ms, 180, x1, y0 + height / 2, height, 5, c, Color.TRANSPARENT_BLACK);
|
||||
|
||||
super.render(ms, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderList(PoseStack p_238478_1_, int p_238478_2_, int p_238478_3_, int p_238478_4_, int p_238478_5_, float p_238478_6_) {
|
||||
Window window = minecraft.getWindow();
|
||||
double d0 = window.getGuiScale();
|
||||
RenderSystem.enableScissor((int) (this.x0 * d0), (int) (window.getHeight() - (this.y1 * d0)), (int) (this.width * d0), (int) (this.height * d0));
|
||||
super.renderList(p_238478_1_, p_238478_2_, p_238478_3_, p_238478_4_, p_238478_5_, p_238478_6_);
|
||||
RenderSystem.disableScissor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
children().stream().filter(e -> e instanceof NumberEntry<?>).forEach(e -> e.mouseClicked(x, y, button));
|
||||
|
||||
return super.mouseClicked(x, y, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowWidth() {
|
||||
return width - 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollbarPosition() {
|
||||
return x0 + this.width - 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
/*for(int i = 0; i < getItemCount(); ++i) {
|
||||
int top = this.getRowTop(i);
|
||||
int bot = top + itemHeight;
|
||||
if (bot >= this.y0 && top <= this.y1)
|
||||
this.getEntry(i).tick();
|
||||
}*/
|
||||
children().forEach(Entry::tick);
|
||||
|
||||
}
|
||||
|
||||
public boolean search(String query) {
|
||||
if (query == null || query.isEmpty()) {
|
||||
setScrollAmount(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
String q = query.toLowerCase(Locale.ROOT);
|
||||
Optional<Entry> first = children().stream().filter(entry -> {
|
||||
if (entry.path == null)
|
||||
return false;
|
||||
|
||||
String[] split = entry.path.split("\\.");
|
||||
String key = split[split.length - 1].toLowerCase(Locale.ROOT);
|
||||
return key.contains(q);
|
||||
}).findFirst();
|
||||
|
||||
if (!first.isPresent()) {
|
||||
setScrollAmount(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
Entry e = first.get();
|
||||
e.annotations.put("highlight", "(:");
|
||||
centerScrollOn(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void bumpCog(float force) {
|
||||
ConfigScreen.cogSpin.bump(3, force);
|
||||
}
|
||||
|
||||
public static abstract class Entry extends ObjectSelectionList.Entry<Entry> implements TickableGuiEventListener {
|
||||
protected List<GuiEventListener> listeners;
|
||||
protected Map<String, String> annotations;
|
||||
protected String path;
|
||||
|
||||
protected Entry() {
|
||||
listeners = new ArrayList<>();
|
||||
annotations = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
return getGuiListeners().stream().anyMatch(l -> l.mouseClicked(x, y, button));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int code, int keyPressed_2_, int keyPressed_3_) {
|
||||
return getGuiListeners().stream().anyMatch(l -> l.keyPressed(code, keyPressed_2_, keyPressed_3_));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char ch, int code) {
|
||||
return getGuiListeners().stream().anyMatch(l -> l.charTyped(ch, code));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {}
|
||||
|
||||
public List<GuiEventListener> getGuiListeners() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
protected void setEditable(boolean b) {}
|
||||
|
||||
protected boolean isCurrentValueChanged() {
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
return ConfigHelper.changes.containsKey(path);
|
||||
}
|
||||
}
|
||||
|
||||
public static class LabeledEntry extends Entry {
|
||||
|
||||
protected static final float labelWidthMult = 0.4f;
|
||||
|
||||
protected TextStencilElement label;
|
||||
protected List<Component> labelTooltip;
|
||||
protected String unit = null;
|
||||
protected LerpedFloat differenceAnimation = LerpedFloat.linear().startWithValue(0);
|
||||
protected LerpedFloat highlightAnimation = LerpedFloat.linear().startWithValue(0);
|
||||
|
||||
public LabeledEntry(String label) {
|
||||
this.label = new TextStencilElement(Minecraft.getInstance().font, label);
|
||||
this.label.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.Key.TEXT_ACCENT_STRONG.p()));
|
||||
labelTooltip = new ArrayList<>();
|
||||
}
|
||||
|
||||
public LabeledEntry(String label, String path) {
|
||||
this(label);
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
differenceAnimation.tickChaser();
|
||||
highlightAnimation.tickChaser();
|
||||
super.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
|
||||
if (isCurrentValueChanged()) {
|
||||
if (differenceAnimation.getChaseTarget() != 1)
|
||||
differenceAnimation.chase(1, .5f, LerpedFloat.Chaser.EXP);
|
||||
} else {
|
||||
if (differenceAnimation.getChaseTarget() != 0)
|
||||
differenceAnimation.chase(0, .6f, LerpedFloat.Chaser.EXP);
|
||||
}
|
||||
|
||||
float animation = differenceAnimation.getValue(partialTicks);
|
||||
if (animation > .1f) {
|
||||
int offset = (int) (30 * (1 - animation));
|
||||
|
||||
if (annotations.containsKey(ConfigAnnotations.RequiresRestart.CLIENT.getName())) {
|
||||
UIRenderHelper.streak(ms, 180, x + width + 10 + offset, y + height / 2, height - 6, 110, new Color(0x50_601010));
|
||||
} else if (annotations.containsKey(ConfigAnnotations.RequiresRelog.TRUE.getName())) {
|
||||
UIRenderHelper.streak(ms, 180, x + width + 10 + offset, y + height / 2, height - 6, 110, new Color(0x40_eefb17));
|
||||
}
|
||||
|
||||
UIRenderHelper.breadcrumbArrow(ms, x - 10 - offset, y + 6, 0, -20, 24, -18, new Color(0x70_ffffff), Color.TRANSPARENT_BLACK);
|
||||
}
|
||||
|
||||
UIRenderHelper.streak(ms, 0, x - 10, y + height / 2, height - 6, width / 8 * 7, new Color(0xdd_000000));
|
||||
UIRenderHelper.streak(ms, 180, x + (int) (width * 1.35f) + 10, y + height / 2, height - 6, width / 8 * 7, new Color(0xdd_000000));
|
||||
MutableComponent component = label.getComponent();
|
||||
Font font = Minecraft.getInstance().font;
|
||||
if (font.width(component) > getLabelWidth(width) - 10) {
|
||||
label.withText(font.substrByWidth(component, getLabelWidth(width) - 15).getString() + "...");
|
||||
}
|
||||
if (unit != null) {
|
||||
int unitWidth = font.width(unit);
|
||||
font.draw(ms, unit, x + getLabelWidth(width) - unitWidth - 5, y + height / 2 + 2, Theme.Key.TEXT_DARKER.i());
|
||||
label.at(x + 10, y + height / 2 - 10, 0).render(ms);
|
||||
} else {
|
||||
label.at(x + 10, y + height / 2 - 4, 0).render(ms);
|
||||
}
|
||||
|
||||
if (annotations.containsKey("highlight")) {
|
||||
highlightAnimation.startWithValue(1).chase(0, 0.1f, LerpedFloat.Chaser.LINEAR);
|
||||
annotations.remove("highlight");
|
||||
}
|
||||
|
||||
animation = highlightAnimation.getValue(partialTicks);
|
||||
if (animation > .01f) {
|
||||
Color highlight = new Color(0xa0_ffffff).scaleAlpha(animation);
|
||||
UIRenderHelper.streak(ms, 0, x - 10, y + height / 2, height - 6, 5, highlight);
|
||||
UIRenderHelper.streak(ms, 180, x + width, y + height / 2, height - 6, 5, highlight);
|
||||
UIRenderHelper.streak(ms, 90, x + width / 2 - 5, y + 3, width + 10, 5, highlight);
|
||||
UIRenderHelper.streak(ms, -90, x + width / 2 - 5, y + height - 3, width + 10, 5, highlight);
|
||||
}
|
||||
|
||||
|
||||
if (mouseX > x && mouseX < x + getLabelWidth(width) && mouseY > y + 5 && mouseY < y + height - 5) {
|
||||
List<Component> tooltip = getLabelTooltip();
|
||||
if (tooltip.isEmpty())
|
||||
return;
|
||||
|
||||
RenderSystem.disableScissor();
|
||||
Screen screen = Minecraft.getInstance().screen;
|
||||
ms.pushPose();
|
||||
ms.translate(0, 0, 400);
|
||||
RemovedGuiUtils.drawHoveringText(ms, tooltip, mouseX, mouseY, screen.width, screen.height, 300, font);
|
||||
ms.popPose();
|
||||
GlStateManager._enableScissorTest();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Component> getLabelTooltip() {
|
||||
return labelTooltip;
|
||||
}
|
||||
|
||||
protected int getLabelWidth(int totalWidth) {
|
||||
return totalWidth;
|
||||
}
|
||||
|
||||
// TODO 1.17
|
||||
@Override
|
||||
public Component getNarration() {
|
||||
return TextComponent.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import net.minecraft.client.gui.Font;
|
||||
|
||||
public class ConfigTextField extends HintableTextFieldWidget {
|
||||
|
||||
public ConfigTextField(Font font, int x, int y, int width, int height) {
|
||||
super(font, x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus(boolean focus) {
|
||||
super.setFocus(focus);
|
||||
|
||||
if (!focus) {
|
||||
if (ConfigScreenList.currentText == this)
|
||||
ConfigScreenList.currentText = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConfigScreenList.currentText != null && ConfigScreenList.currentText != this)
|
||||
ConfigScreenList.currentText.setFocus(false);
|
||||
|
||||
ConfigScreenList.currentText = this;
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
public class HintableTextFieldWidget extends EditBox {
|
||||
|
||||
protected Font font;
|
||||
protected String hint;
|
||||
|
||||
public HintableTextFieldWidget(Font font, int x, int y, int width, int height) {
|
||||
super(font, x, y, width, height, TextComponent.EMPTY);
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
public void setHint(String hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderButton(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
super.renderButton(ms, mouseX, mouseY, partialTicks);
|
||||
|
||||
if (hint == null || hint.isEmpty())
|
||||
return;
|
||||
|
||||
if (!getValue().isEmpty())
|
||||
return;
|
||||
|
||||
font.draw(ms, hint, x + 5, this.y + (this.height - 8) / 2, Theme.Key.TEXT.c().scaleAlpha(.75f).getRGB());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
if (!isMouseOver(x, y))
|
||||
return false;
|
||||
|
||||
if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
|
||||
setValue("");
|
||||
return true;
|
||||
} else
|
||||
return super.mouseClicked(x, y, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) {
|
||||
InputConstants.Key mouseKey = InputConstants.getKey(code, p_keyPressed_2_);
|
||||
if (Minecraft.getInstance().options.keyInventory.isActiveAndMatches(mouseKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_);
|
||||
}
|
||||
}
|
|
@ -1,469 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.electronwill.nightconfig.core.AbstractConfig;
|
||||
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigScreenList.LabeledEntry;
|
||||
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.NumberEntry;
|
||||
import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry;
|
||||
import com.simibubi.create.foundation.config.ui.entries.ValueEntry;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.createmod.catnip.gui.ConfirmationScreen;
|
||||
import net.createmod.catnip.gui.ConfirmationScreen.Response;
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
import net.createmod.catnip.gui.UIRenderHelper;
|
||||
import net.createmod.catnip.gui.element.DelegatedStencilElement;
|
||||
import net.createmod.catnip.gui.widget.BoxWidget;
|
||||
import net.createmod.catnip.utility.Couple;
|
||||
import net.createmod.catnip.utility.FontHelper;
|
||||
import net.createmod.catnip.utility.Pair;
|
||||
import net.createmod.catnip.utility.theme.Color;
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.FormattedText;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
public class SubMenuConfigScreen extends ConfigScreen {
|
||||
|
||||
public final ModConfig.Type type;
|
||||
protected ForgeConfigSpec spec;
|
||||
protected UnmodifiableConfig configGroup;
|
||||
protected ConfigScreenList list;
|
||||
|
||||
protected BoxWidget resetAll;
|
||||
protected BoxWidget saveChanges;
|
||||
protected BoxWidget discardChanges;
|
||||
protected BoxWidget goBack;
|
||||
protected BoxWidget serverLocked;
|
||||
protected HintableTextFieldWidget search;
|
||||
protected int listWidth;
|
||||
protected String title;
|
||||
protected Set<String> highlights = new HashSet<>();
|
||||
|
||||
public static SubMenuConfigScreen find(ConfigHelper.ConfigPath path) {
|
||||
// TODO 1.17: can be null
|
||||
ForgeConfigSpec spec = ConfigHelper.findForgeConfigSpecFor(path.getType(), path.getModID());
|
||||
UnmodifiableConfig values = spec.getValues();
|
||||
BaseConfigScreen base = new BaseConfigScreen(null, path.getModID());
|
||||
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
|
||||
screen.highlights.add(path.getPath()[path.getPath().length - 1]);
|
||||
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) {
|
||||
super(parent);
|
||||
this.type = type;
|
||||
this.spec = configSpec;
|
||||
this.title = title;
|
||||
this.configGroup = configGroup;
|
||||
}
|
||||
|
||||
public SubMenuConfigScreen(Screen parent, ModConfig.Type type, ForgeConfigSpec configSpec) {
|
||||
super(parent);
|
||||
this.type = type;
|
||||
this.spec = configSpec;
|
||||
this.title = "root";
|
||||
this.configGroup = configSpec.getValues();
|
||||
}
|
||||
|
||||
protected void clearChanges() {
|
||||
ConfigHelper.changes.clear();
|
||||
list.children()
|
||||
.stream()
|
||||
.filter(e -> e instanceof ValueEntry)
|
||||
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
|
||||
}
|
||||
|
||||
protected void saveChanges() {
|
||||
UnmodifiableConfig values = spec.getValues();
|
||||
ConfigHelper.changes.forEach((path, change) -> {
|
||||
ForgeConfigSpec.ConfigValue<Object> configValue = values.get(path);
|
||||
configValue.set(change.value);
|
||||
|
||||
if (type == ModConfig.Type.SERVER) {
|
||||
AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(ConfigScreen.modID, path, change.value));
|
||||
}
|
||||
|
||||
String command = change.annotations.get("Execute");
|
||||
if (minecraft.player != null && command != null && command.startsWith("/")) {
|
||||
minecraft.player.chat(command);
|
||||
//AllPackets.channel.sendToServer(new CChatMessagePacket(command));
|
||||
}
|
||||
});
|
||||
clearChanges();
|
||||
}
|
||||
|
||||
protected void resetConfig(UnmodifiableConfig values) {
|
||||
values.valueMap().forEach((key, obj) -> {
|
||||
if (obj instanceof AbstractConfig) {
|
||||
resetConfig((UnmodifiableConfig) obj);
|
||||
} else if (obj instanceof ForgeConfigSpec.ConfigValue) {
|
||||
ForgeConfigSpec.ConfigValue<Object> configValue = (ForgeConfigSpec.ConfigValue<Object>) obj;
|
||||
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw((List<String>) configValue.getPath());
|
||||
|
||||
List<String> comments = new ArrayList<>();
|
||||
|
||||
if (valueSpec.getComment() != null)
|
||||
comments.addAll(Arrays.asList(valueSpec.getComment().split("\n")));
|
||||
|
||||
Pair<String, Map<String, String>> metadata = ConfigHelper.readMetadataFromComment(comments);
|
||||
|
||||
ConfigHelper.setValue(String.join(".", configValue.getPath()), configValue, valueSpec.getDefault(), metadata.getSecond());
|
||||
}
|
||||
});
|
||||
|
||||
list.children()
|
||||
.stream()
|
||||
.filter(e -> e instanceof ValueEntry)
|
||||
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
listWidth = Math.min(width - 80, 300);
|
||||
|
||||
int yCenter = height / 2;
|
||||
int listL = this.width / 2 - listWidth / 2;
|
||||
int listR = this.width / 2 + listWidth / 2;
|
||||
|
||||
resetAll = new BoxWidget(listR + 10, yCenter - 25, 20, 20)
|
||||
.withPadding(2, 2)
|
||||
.withCallback((x, y) ->
|
||||
new ConfirmationScreen()
|
||||
.centered()
|
||||
.withText(FormattedText.of("Resetting all settings of the " + type.toString() + " config. Are you sure?"))
|
||||
.withAction(success -> {
|
||||
if (success)
|
||||
resetConfig(spec.getValues());
|
||||
})
|
||||
.open(this)
|
||||
);
|
||||
|
||||
resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll)));
|
||||
resetAll.getToolTip().add(new TextComponent("Reset All"));
|
||||
resetAll.getToolTip().addAll(FontHelper.cutStringTextComponent("Click here to reset all settings to their default value.", ChatFormatting.GRAY, ChatFormatting.GRAY));
|
||||
|
||||
saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20)
|
||||
.withPadding(2, 2)
|
||||
.withCallback((x, y) -> {
|
||||
if (ConfigHelper.changes.isEmpty())
|
||||
return;
|
||||
|
||||
ConfirmationScreen confirm = new ConfirmationScreen()
|
||||
.centered()
|
||||
.withText(FormattedText.of("Saving " + ConfigHelper.changes.size() + " changed value" + (ConfigHelper.changes.size() != 1 ? "s" : "") + ""))
|
||||
.withAction(success -> {
|
||||
if (success)
|
||||
saveChanges();
|
||||
});
|
||||
|
||||
addAnnotationsToConfirm(confirm).open(this);
|
||||
});
|
||||
saveChanges.showingElement(AllIcons.I_CONFIG_SAVE.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(saveChanges)));
|
||||
saveChanges.getToolTip().add(new TextComponent("Save Changes"));
|
||||
saveChanges.getToolTip().addAll(FontHelper.cutStringTextComponent("Click here to save your current changes.", ChatFormatting.GRAY, ChatFormatting.GRAY));
|
||||
|
||||
discardChanges = new BoxWidget(listL - 30, yCenter + 5, 20, 20)
|
||||
.withPadding(2, 2)
|
||||
.withCallback((x, y) -> {
|
||||
if (ConfigHelper.changes.isEmpty())
|
||||
return;
|
||||
|
||||
new ConfirmationScreen()
|
||||
.centered()
|
||||
.withText(FormattedText.of("Discarding " + ConfigHelper.changes.size() + " unsaved change" + (ConfigHelper.changes.size() != 1 ? "s" : "") + ""))
|
||||
.withAction(success -> {
|
||||
if (success)
|
||||
clearChanges();
|
||||
})
|
||||
.open(this);
|
||||
});
|
||||
discardChanges.showingElement(AllIcons.I_CONFIG_DISCARD.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(discardChanges)));
|
||||
discardChanges.getToolTip().add(new TextComponent("Discard Changes"));
|
||||
discardChanges.getToolTip().addAll(FontHelper.cutStringTextComponent("Click here to discard all the changes you made.", ChatFormatting.GRAY, ChatFormatting.GRAY));
|
||||
|
||||
goBack = new BoxWidget(listL - 30, yCenter + 65, 20, 20)
|
||||
.withPadding(2, 2)
|
||||
.withCallback(this::attemptBackstep);
|
||||
goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(goBack)));
|
||||
goBack.getToolTip().add(new TextComponent("Go Back"));
|
||||
|
||||
addRenderableWidget(resetAll);
|
||||
addRenderableWidget(saveChanges);
|
||||
addRenderableWidget(discardChanges);
|
||||
addRenderableWidget(goBack);
|
||||
|
||||
list = new ConfigScreenList(minecraft, listWidth, height - 80, 35, height - 45, 40);
|
||||
list.setLeftPos(this.width / 2 - list.getWidth() / 2);
|
||||
|
||||
addRenderableWidget(list);
|
||||
|
||||
search = new ConfigTextField(font, width / 2 - listWidth / 2, height - 35, listWidth, 20);
|
||||
search.setResponder(this::updateFilter);
|
||||
search.setHint("Search...");
|
||||
search.moveCursorToStart();
|
||||
addRenderableWidget(search);
|
||||
|
||||
configGroup.valueMap().forEach((key, obj) -> {
|
||||
String humanKey = toHumanReadable(key);
|
||||
|
||||
if (obj instanceof AbstractConfig) {
|
||||
SubMenuEntry entry = new SubMenuEntry(this, humanKey, spec, (UnmodifiableConfig) obj);
|
||||
entry.path = key;
|
||||
list.children().add(entry);
|
||||
if (configGroup.valueMap()
|
||||
.size() == 1)
|
||||
ScreenOpener.open(
|
||||
new SubMenuConfigScreen(parent, humanKey, type, spec, (UnmodifiableConfig) obj));
|
||||
|
||||
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
|
||||
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
|
||||
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
|
||||
Object value = configValue.get();
|
||||
ConfigScreenList.Entry entry = null;
|
||||
|
||||
if (value instanceof Boolean) {
|
||||
entry = new BooleanEntry(humanKey, (ForgeConfigSpec.ConfigValue<Boolean>) configValue, valueSpec);
|
||||
} else if (value instanceof Enum) {
|
||||
entry = new EnumEntry(humanKey, (ForgeConfigSpec.ConfigValue<Enum<?>>) configValue, valueSpec);
|
||||
} else if (value instanceof Number) {
|
||||
entry = NumberEntry.create(value, humanKey, configValue, valueSpec);
|
||||
}
|
||||
|
||||
if (entry == null)
|
||||
entry = new LabeledEntry("Impl missing - " + configValue.get().getClass().getSimpleName() + " " + humanKey + " : " + value);
|
||||
|
||||
if (highlights.contains(key))
|
||||
entry.annotations.put("highlight", ":)");
|
||||
|
||||
list.children().add(entry);
|
||||
}
|
||||
});
|
||||
|
||||
Collections.sort(list.children(),
|
||||
(e, e2) -> {
|
||||
int group = (e2 instanceof SubMenuEntry ? 1 : 0) - (e instanceof SubMenuEntry ? 1 : 0);
|
||||
if (group == 0 && e instanceof LabeledEntry && e2 instanceof LabeledEntry) {
|
||||
LabeledEntry le = (LabeledEntry) e;
|
||||
LabeledEntry le2 = (LabeledEntry) e2;
|
||||
return le.label.getComponent()
|
||||
.getString()
|
||||
.compareTo(le2.label.getComponent()
|
||||
.getString());
|
||||
}
|
||||
return group;
|
||||
});
|
||||
|
||||
list.search(highlights.stream().findFirst().orElse(""));
|
||||
|
||||
//extras for server configs
|
||||
if (type != ModConfig.Type.SERVER)
|
||||
return;
|
||||
if (minecraft.hasSingleplayerServer())
|
||||
return;
|
||||
|
||||
boolean canEdit = minecraft != null && minecraft.player != null && minecraft.player.hasPermissions(2);
|
||||
|
||||
Couple<Color> red = Theme.Key.BUTTON_FAIL.p();
|
||||
Couple<Color> green = Theme.Key.BUTTON_SUCCESS.p();
|
||||
|
||||
DelegatedStencilElement stencil = new DelegatedStencilElement();
|
||||
|
||||
serverLocked = new BoxWidget(listR + 10, yCenter + 5, 20, 20)
|
||||
.withPadding(2, 2)
|
||||
.showingElement(stencil);
|
||||
|
||||
if (!canEdit) {
|
||||
list.children().forEach(e -> e.setEditable(false));
|
||||
resetAll.active = false;
|
||||
stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_LOCKED.render(ms, 0, 0));
|
||||
stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, red));
|
||||
serverLocked.withBorderColors(red);
|
||||
serverLocked.getToolTip().add(new TextComponent("Locked").withStyle(ChatFormatting.BOLD));
|
||||
serverLocked.getToolTip().addAll(FontHelper.cutStringTextComponent("You do not have enough permissions to edit the server config. You can still look at the current values here though.", ChatFormatting.GRAY, ChatFormatting.GRAY));
|
||||
} else {
|
||||
stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.render(ms, 0, 0));
|
||||
stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, green));
|
||||
serverLocked.withBorderColors(green);
|
||||
serverLocked.getToolTip().add(new TextComponent("Unlocked").withStyle(ChatFormatting.BOLD));
|
||||
serverLocked.getToolTip().addAll(FontHelper.cutStringTextComponent("You have enough permissions to edit the server config. Changes you make here will be synced with the server when you save them.", ChatFormatting.GRAY, ChatFormatting.GRAY));
|
||||
}
|
||||
|
||||
addRenderableWidget(serverLocked);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
super.renderWindow(ms, mouseX, mouseY, partialTicks);
|
||||
|
||||
int x = width / 2;
|
||||
drawCenteredString(ms, minecraft.font, ConfigScreen.modID + " > " + type.toString().toLowerCase(Locale.ROOT) + " > " + title, x, 15, Theme.Key.TEXT.i());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderWindowForeground(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||
super.renderWindowForeground(ms, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(@Nonnull Minecraft client, int width, int height) {
|
||||
double scroll = list.getScrollAmount();
|
||||
init(client, width, height);
|
||||
list.setScrollAmount(scroll);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GuiEventListener getFocused() {
|
||||
if (ConfigScreenList.currentText != null)
|
||||
return ConfigScreenList.currentText;
|
||||
|
||||
return super.getFocused();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (super.keyPressed(keyCode, scanCode, modifiers))
|
||||
return true;
|
||||
|
||||
if (Screen.hasControlDown()) {
|
||||
if (keyCode == GLFW.GLFW_KEY_F) {
|
||||
search.setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyCode == GLFW.GLFW_KEY_BACKSPACE) {
|
||||
attemptBackstep();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateFilter(String search) {
|
||||
if (list.search(search)) {
|
||||
this.search.setTextColor(Theme.Key.TEXT.i());
|
||||
} else {
|
||||
this.search.setTextColor(Theme.Key.BUTTON_FAIL.i());
|
||||
}
|
||||
}
|
||||
|
||||
private void attemptBackstep() {
|
||||
if (ConfigHelper.changes.isEmpty() || !(parent instanceof BaseConfigScreen)) {
|
||||
ScreenOpener.open(parent);
|
||||
return;
|
||||
}
|
||||
|
||||
showLeavingPrompt(success -> {
|
||||
if (success == Response.Cancel)
|
||||
return;
|
||||
if (success == Response.Confirm)
|
||||
saveChanges();
|
||||
ConfigHelper.changes.clear();
|
||||
ScreenOpener.open(parent);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
if (ConfigHelper.changes.isEmpty()) {
|
||||
super.onClose();
|
||||
return;
|
||||
}
|
||||
|
||||
showLeavingPrompt(success -> {
|
||||
if (success == Response.Cancel)
|
||||
return;
|
||||
if (success == Response.Confirm)
|
||||
saveChanges();
|
||||
ConfigHelper.changes.clear();
|
||||
super.onClose();
|
||||
});
|
||||
}
|
||||
|
||||
public void showLeavingPrompt(Consumer<ConfirmationScreen.Response> action) {
|
||||
ConfirmationScreen screen = new ConfirmationScreen()
|
||||
.centered()
|
||||
.withThreeActions(action)
|
||||
.addText(FormattedText.of("Leaving with " + ConfigHelper.changes.size() + " unsaved change"
|
||||
+ (ConfigHelper.changes.size() != 1 ? "s" : "") + " for this config"));
|
||||
|
||||
addAnnotationsToConfirm(screen).open(this);
|
||||
}
|
||||
|
||||
private ConfirmationScreen addAnnotationsToConfirm(ConfirmationScreen screen) {
|
||||
AtomicBoolean relog = new AtomicBoolean(false);
|
||||
AtomicBoolean restart = new AtomicBoolean(false);
|
||||
ConfigHelper.changes.values().forEach(change -> {
|
||||
if (change.annotations.containsKey(ConfigAnnotations.RequiresRelog.TRUE.getName()))
|
||||
relog.set(true);
|
||||
|
||||
if (change.annotations.containsKey(ConfigAnnotations.RequiresRestart.CLIENT.getName()))
|
||||
restart.set(true);
|
||||
});
|
||||
|
||||
if (relog.get()) {
|
||||
screen.addText(FormattedText.of(" "));
|
||||
screen.addText(FormattedText.of("At least one changed value will require you to relog to take full effect"));
|
||||
}
|
||||
|
||||
if (restart.get()) {
|
||||
screen.addText(FormattedText.of(" "));
|
||||
screen.addText(FormattedText.of("At least one changed value will require you to restart your game to take full effect"));
|
||||
}
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui.entries;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
|
||||
import net.createmod.catnip.gui.UIRenderHelper;
|
||||
import net.createmod.catnip.gui.element.RenderElement;
|
||||
import net.createmod.catnip.gui.widget.BoxWidget;
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
public class BooleanEntry extends ValueEntry<Boolean> {
|
||||
|
||||
RenderElement enabled;
|
||||
RenderElement disabled;
|
||||
BoxWidget button;
|
||||
|
||||
public BooleanEntry(String label, ForgeConfigSpec.ConfigValue<Boolean> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
super(label, value, spec);
|
||||
|
||||
enabled = AllIcons.I_CONFIRM.asStencil()
|
||||
.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.Key.BUTTON_SUCCESS.p()))
|
||||
.at(10, 0);
|
||||
|
||||
disabled = AllIcons.I_DISABLE.asStencil()
|
||||
.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.Key.BUTTON_FAIL.p()))
|
||||
.at(10, 0);
|
||||
|
||||
button = new BoxWidget().showingElement(enabled)
|
||||
.withCallback(() -> setValue(!getValue()));
|
||||
|
||||
listeners.add(button);
|
||||
onReset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setEditable(boolean b) {
|
||||
super.setEditable(b);
|
||||
button.active = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
button.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY,
|
||||
boolean p_230432_9_, float partialTicks) {
|
||||
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
|
||||
|
||||
button.x = x + width - 80 - resetWidth;
|
||||
button.y = y + 10;
|
||||
button.setWidth(35);
|
||||
button.setHeight(height - 20);
|
||||
button.render(ms, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueChange(Boolean newValue) {
|
||||
super.onValueChange(newValue);
|
||||
button.showingElement(newValue ? enabled : disabled);
|
||||
bumpCog(newValue ? 15f : -16f);
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui.entries;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigScreen;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
|
||||
import net.createmod.catnip.gui.UIRenderHelper;
|
||||
import net.createmod.catnip.gui.element.BoxElement;
|
||||
import net.createmod.catnip.gui.element.DelegatedStencilElement;
|
||||
import net.createmod.catnip.gui.element.TextStencilElement;
|
||||
import net.createmod.catnip.gui.widget.BoxWidget;
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
public class EnumEntry extends ValueEntry<Enum<?>> {
|
||||
|
||||
protected static final int cycleWidth = 34;
|
||||
|
||||
protected TextStencilElement valueText;
|
||||
protected BoxWidget cycleLeft;
|
||||
protected BoxWidget cycleRight;
|
||||
|
||||
public EnumEntry(String label, ForgeConfigSpec.ConfigValue<Enum<?>> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
super(label, value, spec);
|
||||
|
||||
valueText = new TextStencilElement(Minecraft.getInstance().font, "YEP").centered(true, true);
|
||||
valueText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2,
|
||||
height, width, Theme.Key.TEXT.p()));
|
||||
|
||||
DelegatedStencilElement l = AllIcons.I_CONFIG_PREV.asStencil();
|
||||
cycleLeft = new BoxWidget(0, 0, cycleWidth + 8, 16)
|
||||
.withCustomBackground(Theme.Key.PONDER_BACKGROUND_FLAT.c())
|
||||
.showingElement(l)
|
||||
.withCallback(() -> cycleValue(-1));
|
||||
l.withElementRenderer(BoxWidget.gradientFactory.apply(cycleLeft));
|
||||
|
||||
DelegatedStencilElement r = AllIcons.I_CONFIG_NEXT.asStencil();
|
||||
cycleRight = new BoxWidget(0, 0, cycleWidth + 8, 16)
|
||||
.withCustomBackground(Theme.Key.PONDER_BACKGROUND_FLAT.c())
|
||||
.showingElement(r)
|
||||
.withCallback(() -> cycleValue(1));
|
||||
r.at(cycleWidth - 8, 0);
|
||||
r.withElementRenderer(BoxWidget.gradientFactory.apply(cycleRight));
|
||||
|
||||
listeners.add(cycleLeft);
|
||||
listeners.add(cycleRight);
|
||||
|
||||
onReset();
|
||||
}
|
||||
|
||||
protected void cycleValue(int direction) {
|
||||
Enum<?> e = getValue();
|
||||
Enum<?>[] options = e.getDeclaringClass()
|
||||
.getEnumConstants();
|
||||
e = options[Math.floorMod(e.ordinal() + direction, options.length)];
|
||||
setValue(e);
|
||||
bumpCog(direction * 15f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setEditable(boolean b) {
|
||||
super.setEditable(b);
|
||||
cycleLeft.active = b;
|
||||
cycleLeft.animateGradientFromState();
|
||||
cycleRight.active = b;
|
||||
cycleRight.animateGradientFromState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
cycleLeft.tick();
|
||||
cycleRight.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY,
|
||||
boolean p_230432_9_, float partialTicks) {
|
||||
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
|
||||
|
||||
cycleLeft.x = x + getLabelWidth(width) + 4;
|
||||
cycleLeft.y = y + 10;
|
||||
cycleLeft.render(ms, mouseX, mouseY, partialTicks);
|
||||
|
||||
valueText.at(cycleLeft.x + cycleWidth - 8, y + 10, 200)
|
||||
.withBounds(width - getLabelWidth(width) - 2 * cycleWidth - resetWidth - 4, 16)
|
||||
.render(ms);
|
||||
|
||||
cycleRight.x = x + width - cycleWidth * 2 - resetWidth + 10;
|
||||
cycleRight.y = y + 10;
|
||||
cycleRight.render(ms, mouseX, mouseY, partialTicks);
|
||||
|
||||
new BoxElement()
|
||||
.withBackground(Theme.Key.PONDER_BACKGROUND_FLAT.c())
|
||||
.flatBorder(0x01_000000)
|
||||
.withBounds(48, 6)
|
||||
.at(cycleLeft.x + 22, cycleLeft.y + 5)
|
||||
.render(ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueChange(Enum<?> newValue) {
|
||||
super.onValueChange(newValue);
|
||||
valueText.withText(ConfigScreen.toHumanReadable(newValue.name().toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
}
|
|
@ -1,246 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui.entries;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigTextField;
|
||||
|
||||
import net.createmod.catnip.utility.theme.Theme;
|
||||
import net.createmod.catnip.gui.UIRenderHelper;
|
||||
import net.createmod.catnip.gui.element.TextStencilElement;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
|
||||
|
||||
protected int minOffset = 0, maxOffset = 0;
|
||||
protected TextStencilElement minText = null, maxText = null;
|
||||
protected EditBox textField;
|
||||
|
||||
@Nullable
|
||||
public static NumberEntry<? extends Number> create(Object type, String label, ForgeConfigSpec.ConfigValue<?> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
if (type instanceof Integer) {
|
||||
return new IntegerEntry(label, (ForgeConfigSpec.ConfigValue<Integer>) value, spec);
|
||||
} else if (type instanceof Float) {
|
||||
return new FloatEntry(label, (ForgeConfigSpec.ConfigValue<Float>) value, spec);
|
||||
} else if (type instanceof Double) {
|
||||
return new DoubleEntry(label, (ForgeConfigSpec.ConfigValue<Double>) value, spec);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public NumberEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
super(label, value, spec);
|
||||
textField = new ConfigTextField(Minecraft.getInstance().font, 0, 0, 200, 20);
|
||||
if (this instanceof IntegerEntry && annotations.containsKey("IntDisplay")) {
|
||||
String intDisplay = annotations.get("IntDisplay");
|
||||
int intValue = (Integer) getValue();
|
||||
String textValue;
|
||||
switch (intDisplay) {
|
||||
case "#":
|
||||
textValue = "#" + Integer.toHexString(intValue).toUpperCase(Locale.ROOT);
|
||||
break;
|
||||
case "0x":
|
||||
textValue = "0x" + Integer.toHexString(intValue).toUpperCase(Locale.ROOT);
|
||||
break;
|
||||
case "0b":
|
||||
textValue = "0b" + Integer.toBinaryString(intValue);
|
||||
break;
|
||||
default:
|
||||
textValue = String.valueOf(intValue);
|
||||
}
|
||||
textField.setValue(textValue);
|
||||
} else {
|
||||
textField.setValue(String.valueOf(getValue()));
|
||||
}
|
||||
textField.setTextColor(Theme.Key.TEXT.i());
|
||||
|
||||
Object range = spec.getRange();
|
||||
try {
|
||||
Field minField = range.getClass().getDeclaredField("min");
|
||||
Field maxField = range.getClass().getDeclaredField("max");
|
||||
minField.setAccessible(true);
|
||||
maxField.setAccessible(true);
|
||||
T min = (T) minField.get(range);
|
||||
T max = (T) maxField.get(range);
|
||||
|
||||
Font font = Minecraft.getInstance().font;
|
||||
if (min.doubleValue() > getTypeMin().doubleValue()) {
|
||||
TextComponent t = new TextComponent(formatBound(min) + " < ");
|
||||
minText = new TextStencilElement(font, t).centered(true, false);
|
||||
minText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.Key.TEXT_DARKER.p()));
|
||||
minOffset = font.width(t);
|
||||
}
|
||||
if (max.doubleValue() < getTypeMax().doubleValue()) {
|
||||
TextComponent t = new TextComponent(" < " + formatBound(max));
|
||||
maxText = new TextStencilElement(font, t).centered(true, false);
|
||||
maxText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.Key.TEXT_DARKER.p()));
|
||||
maxOffset = font.width(t);
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException | ClassCastException | NullPointerException ignored) {
|
||||
|
||||
}
|
||||
|
||||
textField.setResponder(s -> {
|
||||
try {
|
||||
T number = getParser().apply(s);
|
||||
if (!spec.test(number))
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
textField.setTextColor(Theme.Key.TEXT.i());
|
||||
setValue(number);
|
||||
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
textField.setTextColor(Theme.Key.BUTTON_FAIL.i());
|
||||
}
|
||||
});
|
||||
|
||||
textField.moveCursorToStart();
|
||||
listeners.add(textField);
|
||||
onReset();
|
||||
}
|
||||
|
||||
protected String formatBound(T bound) {
|
||||
String sci = String.format("%.2E", bound.doubleValue());
|
||||
String str = String.valueOf(bound);
|
||||
return sci.length() < str.length() ? sci : str;
|
||||
}
|
||||
|
||||
protected abstract T getTypeMin();
|
||||
|
||||
protected abstract T getTypeMax();
|
||||
|
||||
protected abstract Function<String, T> getParser();
|
||||
|
||||
@Override
|
||||
protected void setEditable(boolean b) {
|
||||
super.setEditable(b);
|
||||
textField.setEditable(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueChange(T newValue) {
|
||||
super.onValueChange(newValue);
|
||||
|
||||
try {
|
||||
T current = getParser().apply(textField.getValue());
|
||||
if (!current.equals(newValue)) {
|
||||
textField.setValue(String.valueOf(newValue));
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
textField.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
|
||||
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
|
||||
|
||||
textField.x = x + width - 82 - resetWidth;
|
||||
textField.y = y + 8;
|
||||
textField.setWidth(Math.min(width - getLabelWidth(width) - resetWidth - minOffset - maxOffset, 40));
|
||||
textField.setHeight(20);
|
||||
textField.render(ms, mouseX, mouseY, partialTicks);
|
||||
|
||||
if (minText != null)
|
||||
minText
|
||||
.at(textField.x - minOffset, textField.y, 0)
|
||||
.withBounds(minOffset, textField.getHeight())
|
||||
.render(ms);
|
||||
|
||||
if (maxText != null)
|
||||
maxText
|
||||
.at(textField.x + textField.getWidth(), textField.y, 0)
|
||||
.withBounds(maxOffset, textField.getHeight())
|
||||
.render(ms);
|
||||
}
|
||||
|
||||
public static class IntegerEntry extends NumberEntry<Integer> {
|
||||
|
||||
public IntegerEntry(String label, ForgeConfigSpec.ConfigValue<Integer> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
super(label, value, spec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer getTypeMin() {
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer getTypeMax() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<String, Integer> getParser() {
|
||||
return (string) -> {
|
||||
if (string.startsWith("#")) {
|
||||
return Integer.parseUnsignedInt(string.substring(1), 16);
|
||||
} else if (string.startsWith("0x")) {
|
||||
return Integer.parseUnsignedInt(string.substring(2), 16);
|
||||
} else if (string.startsWith("0b")) {
|
||||
return Integer.parseUnsignedInt(string.substring(2), 2);
|
||||
} else {
|
||||
return Integer.parseInt(string);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class FloatEntry extends NumberEntry<Float> {
|
||||
|
||||
public FloatEntry(String label, ForgeConfigSpec.ConfigValue<Float> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
super(label, value, spec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Float getTypeMin() {
|
||||
return -Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Float getTypeMax() {
|
||||
return Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<String, Float> getParser() {
|
||||
return Float::parseFloat;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DoubleEntry extends NumberEntry<Double> {
|
||||
|
||||
public DoubleEntry(String label, ForgeConfigSpec.ConfigValue<Double> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
super(label, value, spec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Double getTypeMin() {
|
||||
return (double) -Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Double getTypeMax() {
|
||||
return (double) Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<String, Double> getParser() {
|
||||
return Double::parseDouble;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui.entries;
|
||||
|
||||
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
|
||||
import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
import net.createmod.catnip.gui.element.DelegatedStencilElement;
|
||||
import net.createmod.catnip.gui.widget.BoxWidget;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
|
||||
|
||||
protected BoxWidget button;
|
||||
|
||||
public SubMenuEntry(SubMenuConfigScreen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) {
|
||||
super(label);
|
||||
|
||||
button = new BoxWidget(0, 0, 35, 16)
|
||||
.showingElement(AllIcons.I_CONFIG_OPEN.asStencil().at(10, 0))
|
||||
.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config)));
|
||||
button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(button)));
|
||||
|
||||
listeners.add(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
button.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
|
||||
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
|
||||
|
||||
button.x = x + width - 108;
|
||||
button.y = y + 10;
|
||||
button.setHeight(height - 20);
|
||||
button.render(ms, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLabelWidth(int totalWidth) {
|
||||
return (int) (totalWidth * labelWidthMult) + 30;
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
package com.simibubi.create.foundation.config.ui.entries;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigAnnotations;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigHelper;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigScreen;
|
||||
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
|
||||
import net.createmod.catnip.gui.element.DelegatedStencilElement;
|
||||
import net.createmod.catnip.gui.widget.BoxWidget;
|
||||
import net.createmod.catnip.utility.FontHelper;
|
||||
import net.createmod.catnip.utility.Pair;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
|
||||
|
||||
protected static final int resetWidth = 28;//including 6px offset on either side
|
||||
|
||||
protected ForgeConfigSpec.ConfigValue<T> value;
|
||||
protected ForgeConfigSpec.ValueSpec spec;
|
||||
protected BoxWidget resetButton;
|
||||
protected boolean editable = true;
|
||||
|
||||
public ValueEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
|
||||
super(label);
|
||||
this.value = value;
|
||||
this.spec = spec;
|
||||
this.path = String.join(".", value.getPath());
|
||||
|
||||
resetButton = new BoxWidget(0, 0, resetWidth - 12, 16)
|
||||
.showingElement(AllIcons.I_CONFIG_RESET.asStencil())
|
||||
.withCallback(() -> {
|
||||
setValue((T) spec.getDefault());
|
||||
this.onReset();
|
||||
});
|
||||
resetButton.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(resetButton)));
|
||||
|
||||
listeners.add(resetButton);
|
||||
|
||||
List<String> path = value.getPath();
|
||||
labelTooltip.add(new TextComponent(label).withStyle(ChatFormatting.WHITE));
|
||||
String comment = spec.getComment();
|
||||
if (comment == null || comment.isEmpty())
|
||||
return;
|
||||
|
||||
List<String> commentLines = new ArrayList<>(Arrays.asList(comment.split("\n")));
|
||||
|
||||
|
||||
Pair<String, Map<String, String>> metadata = ConfigHelper.readMetadataFromComment(commentLines);
|
||||
if (metadata.getFirst() != null) {
|
||||
unit = metadata.getFirst();
|
||||
}
|
||||
if (metadata.getSecond() != null && !metadata.getSecond().isEmpty()) {
|
||||
annotations.putAll(metadata.getSecond());
|
||||
}
|
||||
// add comment to tooltip
|
||||
labelTooltip.addAll(commentLines.stream()
|
||||
.filter(Predicates.not(s -> s.startsWith("Range")))
|
||||
.map(TextComponent::new)
|
||||
.flatMap(stc -> FontHelper.cutTextComponent(stc, ChatFormatting.GRAY, ChatFormatting.GRAY)
|
||||
.stream())
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
if (annotations.containsKey(ConfigAnnotations.RequiresRelog.TRUE.getName()))
|
||||
labelTooltip.addAll(FontHelper.cutTextComponent(new TextComponent("Changing this value will require a _relog_ to take full effect"), ChatFormatting.GRAY, ChatFormatting.GOLD));
|
||||
|
||||
if (annotations.containsKey(ConfigAnnotations.RequiresRestart.CLIENT.getName()))
|
||||
labelTooltip.addAll(FontHelper.cutTextComponent(new TextComponent("Changing this value will require a _restart_ to take full effect"), ChatFormatting.GRAY, ChatFormatting.RED));
|
||||
|
||||
labelTooltip.add(new TextComponent(ConfigScreen.modID + ":" + path.get(path.size() - 1)).withStyle(ChatFormatting.DARK_GRAY));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setEditable(boolean b) {
|
||||
editable = b;
|
||||
resetButton.active = editable && !isCurrentValueDefault();
|
||||
resetButton.animateGradientFromState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
resetButton.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
|
||||
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
|
||||
|
||||
resetButton.x = x + width - resetWidth + 6;
|
||||
resetButton.y = y + 10;
|
||||
resetButton.render(ms, mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLabelWidth(int totalWidth) {
|
||||
return (int) (totalWidth * labelWidthMult) + 30;
|
||||
}
|
||||
|
||||
public void setValue(@Nonnull T value) {
|
||||
ConfigHelper.setValue(path, this.value, value, annotations);
|
||||
onValueChange(value);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public T getValue() {
|
||||
return ConfigHelper.getValue(path, this.value);
|
||||
}
|
||||
|
||||
protected boolean isCurrentValueDefault() {
|
||||
return spec.getDefault().equals(getValue());
|
||||
}
|
||||
|
||||
public void onReset() {
|
||||
onValueChange(getValue());
|
||||
}
|
||||
|
||||
public void onValueChange() {
|
||||
onValueChange(getValue());
|
||||
}
|
||||
public void onValueChange(T newValue) {
|
||||
resetButton.active = editable && !isCurrentValueDefault();
|
||||
resetButton.animateGradientFromState();
|
||||
}
|
||||
|
||||
protected void bumpCog() {bumpCog(10f);}
|
||||
protected void bumpCog(float force) {
|
||||
if (list != null && list instanceof ConfigScreenList)
|
||||
((ConfigScreenList) list).bumpCog(force);
|
||||
}
|
||||
}
|
|
@ -6,9 +6,9 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
|||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
|
||||
import com.simibubi.create.foundation.utility.CreateLang;
|
||||
|
||||
import net.createmod.catnip.config.ui.BaseConfigScreen;
|
||||
import net.createmod.catnip.gui.AbstractSimiScreen;
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
import net.createmod.catnip.gui.element.BoxElement;
|
||||
|
@ -147,7 +147,7 @@ public class CreateMainMenuScreen extends AbstractSimiScreen {
|
|||
addRenderableWidget(
|
||||
new Button(center - 100, yStart + 92, bLongWidth, bHeight, CreateLang.translateDirect("menu.return"), $ -> linkTo(parent)));
|
||||
addRenderableWidget(new Button(center - 100, yStart + 24 + -16, bLongWidth, bHeight, CreateLang.translateDirect("menu.configure"),
|
||||
$ -> linkTo(BaseConfigScreen.forCreate(this))));
|
||||
$ -> linkTo(new BaseConfigScreen(this, Create.ID))));
|
||||
|
||||
gettingStarted = new Button(center + 2, yStart + 48 + -16, bShortWidth, bHeight,
|
||||
CreateLang.translateDirect("menu.ponder_index"), $ -> linkTo(new PonderTagIndexScreen()));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.simibubi.create.foundation.config.ui;
|
||||
package com.simibubi.create.foundation.gui.widget;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -10,8 +10,8 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
|||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.gui.CreateMainMenuScreen;
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
|
||||
import net.createmod.catnip.gui.ScreenOpener;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Button;
|
|
@ -75,8 +75,7 @@ import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
|
|||
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
|
||||
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
|
||||
import com.simibubi.create.foundation.command.HighlightPacket;
|
||||
import com.simibubi.create.foundation.command.SConfigureConfigPacket;
|
||||
import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket;
|
||||
import com.simibubi.create.foundation.command.SimpleCreateActions;
|
||||
import com.simibubi.create.foundation.gui.container.ClearContainerPacket;
|
||||
import com.simibubi.create.foundation.gui.container.GhostItemSubmitPacket;
|
||||
import com.simibubi.create.foundation.tileEntity.RemoveTileEntityPacket;
|
||||
|
@ -84,6 +83,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCo
|
|||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
|
||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||
|
||||
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -123,7 +123,7 @@ public enum AllPackets {
|
|||
LINKED_CONTROLLER_BIND(LinkedControllerBindPacket.class, LinkedControllerBindPacket::new, PLAY_TO_SERVER),
|
||||
LINKED_CONTROLLER_USE_LECTERN(LinkedControllerStopLecternPacket.class, LinkedControllerStopLecternPacket::new,
|
||||
PLAY_TO_SERVER),
|
||||
C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER),
|
||||
//C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER),
|
||||
SUBMIT_GHOST_ITEM(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new, PLAY_TO_SERVER),
|
||||
BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new,
|
||||
PLAY_TO_SERVER),
|
||||
|
@ -153,7 +153,7 @@ public enum AllPackets {
|
|||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
|
||||
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
|
||||
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT),
|
||||
S_CONFIGURE_CONFIG(SConfigureConfigPacket.class, SConfigureConfigPacket::new, PLAY_TO_CLIENT),
|
||||
//S_CONFIGURE_CONFIG(SConfigureConfigPacket.class, SConfigureConfigPacket::new, PLAY_TO_CLIENT),
|
||||
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
|
||||
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
|
||||
CONTRAPTION_BLOCK_CHANGED(ContraptionBlockChangedPacket.class, ContraptionBlockChangedPacket::new, PLAY_TO_CLIENT),
|
||||
|
@ -192,6 +192,18 @@ public enum AllPackets {
|
|||
public static final String NETWORK_VERSION_STR = String.valueOf(NETWORK_VERSION);
|
||||
public static SimpleChannel channel;
|
||||
|
||||
static {
|
||||
ClientboundSimpleActionPacket.addAction("rainbowDebug", () -> SimpleCreateActions::rainbowDebug);
|
||||
ClientboundSimpleActionPacket.addAction("overlayReset", () -> SimpleCreateActions::overlayReset);
|
||||
ClientboundSimpleActionPacket.addAction("overlayScreen", () -> SimpleCreateActions::overlayScreen);
|
||||
ClientboundSimpleActionPacket.addAction("experimentalLighting", () -> SimpleCreateActions::experimentalLighting);
|
||||
ClientboundSimpleActionPacket.addAction("fabulousWarning", () -> SimpleCreateActions::fabulousWarning);
|
||||
ClientboundSimpleActionPacket.addAction("zoomMultiplier", () -> SimpleCreateActions::zoomMultiplier);
|
||||
ClientboundSimpleActionPacket.addAction("camAngleYawTarget", () -> value -> SimpleCreateActions.camAngleTarget(value, true));
|
||||
ClientboundSimpleActionPacket.addAction("camAnglePitchTarget", () -> value -> SimpleCreateActions.camAngleTarget(value, false));
|
||||
ClientboundSimpleActionPacket.addAction("camAngleFunction", () -> SimpleCreateActions::camAngleFunction);
|
||||
}
|
||||
|
||||
private LoadedPacket<?> packet;
|
||||
|
||||
<T extends SimplePacketBase> AllPackets(Class<T> type, Function<FriendlyByteBuf, T> factory,
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.simibubi.create.foundation.ponder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock;
|
||||
import com.simibubi.create.foundation.ponder.content.ArmScenes;
|
||||
import com.simibubi.create.foundation.ponder.content.BearingScenes;
|
||||
import com.simibubi.create.foundation.ponder.content.BeltScenes;
|
||||
|
@ -45,15 +49,28 @@ import com.tterrag.registrate.util.entry.ItemProviderEntry;
|
|||
import com.tterrag.registrate.util.entry.RegistryEntry;
|
||||
|
||||
import net.createmod.ponder.foundation.CustomPonderRegistrationHelper;
|
||||
import net.createmod.ponder.foundation.content.DebugScenes;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
public class CreatePonderIndex {
|
||||
|
||||
private static final CustomPonderRegistrationHelper<ItemProviderEntry<?>> HELPER = new CustomPonderRegistrationHelper<>(Create.ID, RegistryEntry::getId);
|
||||
|
||||
public static final boolean REGISTER_DEBUG_SCENES = false;
|
||||
public static final List<Predicate<ItemLike>> INDEX_SCREEN_EXCLUSIONS = List.of(
|
||||
itemLike -> {
|
||||
if (!(itemLike instanceof BlockItem blockItem))
|
||||
return false;
|
||||
|
||||
Block block = blockItem.getBlock();
|
||||
if (!(block instanceof ValveHandleBlock))
|
||||
return false;
|
||||
|
||||
return !AllBlocks.COPPER_VALVE_HANDLE.is(block);
|
||||
}
|
||||
);
|
||||
|
||||
public static void register() {
|
||||
// Register storyboards here
|
||||
|
@ -364,10 +381,6 @@ public class CreatePonderIndex {
|
|||
.addStoryBoard("steam_whistle", SteamScenes::whistle);
|
||||
HELPER.forComponents(AllBlocks.STEAM_ENGINE)
|
||||
.addStoryBoard("steam_engine", SteamScenes::engine);
|
||||
|
||||
// Debug scenes, can be found in game via the Brass Hand
|
||||
if (REGISTER_DEBUG_SCENES)
|
||||
DebugScenes.registerAll();
|
||||
}
|
||||
public static void registerTags() {
|
||||
// Add items to tags here
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.simibubi.create.foundation.ponder;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.createmod.ponder.foundation.PonderPlugin;
|
||||
import net.createmod.ponder.foundation.PonderWorld;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
|
||||
public class CreatePonderPlugin implements PonderPlugin {
|
||||
|
||||
@Override
|
||||
public void registerScenes() {
|
||||
CreatePonderIndex.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTags() {
|
||||
CreatePonderIndex.registerTags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPonderWorldRestore(PonderWorld world) {
|
||||
PonderWorldTileFix.fixControllerTiles(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Predicate<ItemLike>> indexExclusions() {
|
||||
return CreatePonderIndex.INDEX_SCREEN_EXCLUSIONS.stream();
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package com.simibubi.create.foundation.ponder.content;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.ponder.CreateSceneBuilder;
|
||||
|
||||
import net.createmod.catnip.utility.Pointing;
|
||||
import net.createmod.ponder.enums.PonderGuiTextures;
|
||||
import net.createmod.ponder.foundation.ElementLink;
|
||||
import net.createmod.ponder.foundation.PonderPalette;
|
||||
import net.createmod.ponder.foundation.SceneBuilder;
|
||||
|
@ -62,7 +62,7 @@ public class ItemVaultScenes {
|
|||
ItemStack hand = AllItems.BRASS_HAND.asStack();
|
||||
scene.overlay
|
||||
.showControls(new InputWindowElement(util.vector.blockSurface(frontVault, Direction.NORTH), Pointing.RIGHT)
|
||||
.showing(AllIcons.I_MTD_CLOSE)
|
||||
.showing(PonderGuiTextures.ICON_PONDER_CLOSE)
|
||||
.withItem(hand), 40);
|
||||
scene.idle(7);
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock;
|
|||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity;
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.ponder.CreateSceneBuilder;
|
||||
|
||||
import net.createmod.catnip.utility.Pointing;
|
||||
import net.createmod.catnip.utility.VecHelper;
|
||||
import net.createmod.ponder.enums.PonderGuiTextures;
|
||||
import net.createmod.ponder.foundation.ElementLink;
|
||||
import net.createmod.ponder.foundation.PonderPalette;
|
||||
import net.createmod.ponder.foundation.SceneBuilder;
|
||||
|
@ -162,7 +162,7 @@ public class FluidTankScenes {
|
|||
ItemStack bucket = new ItemStack(Items.BUCKET, 1);
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH), Pointing.RIGHT)
|
||||
.showing(AllIcons.I_MTD_CLOSE)
|
||||
.showing(PonderGuiTextures.ICON_PONDER_CLOSE)
|
||||
.withItem(bucket),
|
||||
40);
|
||||
scene.idle(7);
|
||||
|
|
|
@ -5,12 +5,12 @@ import com.simibubi.create.Create;
|
|||
import com.simibubi.create.content.contraptions.fluids.FluidFX;
|
||||
import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity;
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
import com.simibubi.create.foundation.ponder.CreateSceneBuilder;
|
||||
import com.simibubi.create.foundation.ponder.element.BeltItemElement;
|
||||
|
||||
import net.createmod.catnip.utility.Pointing;
|
||||
import net.createmod.catnip.utility.VecHelper;
|
||||
import net.createmod.ponder.enums.PonderGuiTextures;
|
||||
import net.createmod.ponder.foundation.ElementLink;
|
||||
import net.createmod.ponder.foundation.PonderPalette;
|
||||
import net.createmod.ponder.foundation.SceneBuilder;
|
||||
|
@ -74,7 +74,7 @@ public class SpoutScenes {
|
|||
.getBucket(honey);
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.NORTH), Pointing.RIGHT)
|
||||
.showing(AllIcons.I_MTD_CLOSE)
|
||||
.showing(PonderGuiTextures.ICON_PONDER_CLOSE)
|
||||
.withItem(bucket),
|
||||
40);
|
||||
scene.idle(7);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
public net.minecraft.client.Minecraft f_91013_ # pausePartialTick
|
||||
public net.minecraft.client.gui.Font m_92863_(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/gui/font/FontSet; # getFontSet
|
||||
public net.minecraft.client.gui.screens.TitleScreen f_96729_ # panorama
|
||||
public net.minecraft.client.multiplayer.ClientPacketListener f_104897_ # serverChunkRadius
|
||||
|
@ -7,8 +6,6 @@ public net.minecraft.client.renderer.ItemInHandRenderer f_109300_ # mainHandItem
|
|||
public net.minecraft.client.renderer.ItemInHandRenderer f_109301_ # offHandItem
|
||||
public net.minecraft.client.renderer.entity.ItemRenderer f_115096_ # textureManager
|
||||
|
||||
public-f net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket f_132663_ # flyingSpeed
|
||||
|
||||
public net.minecraft.server.MinecraftServer f_129744_ # storageSource
|
||||
public net.minecraft.server.network.ServerGamePacketListenerImpl f_9737_ # aboveGroundTickCount
|
||||
|
||||
|
@ -40,4 +37,4 @@ public net.minecraft.client.model.AgeableListModel f_102011_ # babyBodyScale
|
|||
public net.minecraft.client.model.AgeableListModel f_102012_ # bodyYOffset
|
||||
|
||||
public net.minecraft.client.gui.components.CommandSuggestions f_93866_ # suggestions
|
||||
public net.minecraft.client.gui.components.CommandSuggestions$SuggestionsList <init>(Lnet/minecraft/client/gui/components/CommandSuggestions;IIILjava/util/List;Z)V # <init>
|
||||
public net.minecraft.client.gui.components.CommandSuggestions$SuggestionsList <init>(Lnet/minecraft/client/gui/components/CommandSuggestions;IIILjava/util/List;Z)V # <init>
|
||||
|
|
Loading…
Reference in a new issue