diff --git a/common/src/main/java/org/vivecraft/client/ClientConfig.java b/common/src/main/java/org/vivecraft/client/ClientConfig.java new file mode 100644 index 000000000..16dd469c5 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/ClientConfig.java @@ -0,0 +1,915 @@ +package org.vivecraft.client; + +import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.Config; +import com.electronwill.nightconfig.core.ConfigSpec; +import com.electronwill.nightconfig.core.file.CommentedFileConfig; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.vivecraft.client_vr.gui.PhysicalKeyboard; +import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.common.ConfigBuilder; +import org.vivecraft.common.utils.math.Angle; + +import java.util.List; + +public class ClientConfig { + + //Keyboard + public static ConfigBuilder.BooleanValue physicalKeyboard; + public static ConfigBuilder.BooleanValue autoOpenKeyboard; + public static ConfigBuilder.BooleanValue alwaysSimulateKeyboard; + public static ConfigBuilder.StringValue keyboardKeys; + public static ConfigBuilder.StringValue keyboardKeysShift; + public static ConfigBuilder.DoubleValue physicalKeyboardScale; + public static ConfigBuilder.EnumValue physicalKeyboardTheme; + + //MR + public static ConfigBuilder.VectorValue mrMovingCamOffset; + public static ConfigBuilder.QuatValue mrMovingCamOffsetRot; + public static ConfigBuilder.StringValue mixedRealityKeyColor; + public static ConfigBuilder.BooleanValue mixedRealityAlphaMask; + public static ConfigBuilder.IntValue mixedRealityFov; + public static ConfigBuilder.BooleanValue mixedRealityRenderCameraModel; + public static ConfigBuilder.BooleanValue mixedRealityUndistorted; + public static ConfigBuilder.BooleanValue mixedRealityUnityLike; + public static ConfigBuilder.BooleanValue mixedRealityRenderHands; + + //Roomscale + public static ConfigBuilder.BooleanValue realisticSneakEnabled; + public static ConfigBuilder.DoubleValue sneakThreshold; + public static ConfigBuilder.BooleanValue realisticJumpEnabled; + public static ConfigBuilder.DoubleValue jumpThreshold; + public static ConfigBuilder.BooleanValue autoSprint; + public static ConfigBuilder.DoubleValue autoSprintThreshold; + public static ConfigBuilder.BooleanValue allowCrawling; + public static ConfigBuilder.DoubleValue crawlThreshold; + public static ConfigBuilder.BooleanValue realisticClimbEnabled; + public static ConfigBuilder.BooleanValue realisticRowEnabled; + public static ConfigBuilder.BooleanValue realisticSwimEnabled; + public static ConfigBuilder.DoubleValue movementSpeedMultiplier; + public static ConfigBuilder.DoubleValue walkMultiplier; + public static ConfigBuilder.EnumValue weaponCollision; + public static ConfigBuilder.EnumValue bowMode; + public static ConfigBuilder.BooleanValue walkUpBlocks; + public static ConfigBuilder.BooleanValue backpackSwitching; + public static ConfigBuilder.BooleanValue vrTouchHotbar; + public static ConfigBuilder.BooleanValue guiAppearOverBlock; + public static ConfigBuilder.BooleanValue physicalGuiEnabled; + public static ConfigBuilder.EnumValue inertiaFactor; //TODO just use a number? + public static ConfigBuilder.BooleanValue vehicleRotation; + + //Display + public static ConfigBuilder.EnumValue displayMirrorMode; + public static ConfigBuilder.BooleanValue useCrosshairOcclusion; + public static ConfigBuilder.DoubleValue menuCrosshairScale; + public static ConfigBuilder.BooleanValue crosshairScalesWithDistance; + public static ConfigBuilder.BooleanValue menuBackground; + public static ConfigBuilder.BooleanValue menuAlwaysFollowFace; + public static ConfigBuilder.EnumValue renderInGameCrosshairMode; + public static ConfigBuilder.EnumValue shaderGUIRender; + public static ConfigBuilder.BooleanValue hideGUI; + public static ConfigBuilder.DoubleValue crosshairScale; + public static ConfigBuilder.DoubleValue renderScaleFactor; + + //HUD + public static ConfigBuilder.BooleanValue lowHealthIndicator; + public static ConfigBuilder.DoubleValue hudDistance; + public static ConfigBuilder.DoubleValue hudPitchOffset; + public static ConfigBuilder.DoubleValue hudYawOffset; + public static ConfigBuilder.BooleanValue stencilOn; + public static ConfigBuilder.DoubleValue headHudScale; + public static ConfigBuilder.DoubleValue headToHmdLength; + public static ConfigBuilder.BooleanValue hudOcclusion; + public static ConfigBuilder.DoubleValue hudOpacity; + public static ConfigBuilder.EnumValue vrHudLockMode; + + //Camera + public static ConfigBuilder.DoubleValue handCameraResScale; + public static ConfigBuilder.IntValue handCameraFov; + public static ConfigBuilder.VectorValue vrFixedCampos; + public static ConfigBuilder.QuatValue vrFixedCamrot; + public static ConfigBuilder.EnumValue externalCameraAngleOrder; + + //Update + public static ConfigBuilder.BooleanValue firstRun; + public static ConfigBuilder.StringValue lastUpdate; + public static ConfigBuilder.BooleanValue alwaysShowUpdates; + public static ConfigBuilder.EnumValue chatNotifications; + public static ConfigBuilder.BooleanValue showServerPluginMessage; + public static ConfigBuilder.StringValue chatNotificationSound; + + //Teleport + public static ConfigBuilder.BooleanValue limitedTeleport; //Server setting? + public static ConfigBuilder.IntValue teleportLimitDown; //Vector? + public static ConfigBuilder.IntValue teleportLimitHoriz; + public static ConfigBuilder.IntValue teleportLimitUp; + + //Seated + public static ConfigBuilder.BooleanValue seated; + public static ConfigBuilder.BooleanValue seatedhmd; + public static ConfigBuilder.BooleanValue seatedHudAltMode; + public static ConfigBuilder.BooleanValue seatedFreeMove; + public static ConfigBuilder.BooleanValue forceStandingFreeMove; + public static ConfigBuilder.EnumValue vrFreeMoveFlyMode; //TODO check + public static ConfigBuilder.EnumValue vrFreeMoveMode; + + + //General + public static ConfigBuilder.BooleanValue vrHotswitchingEnabled; + public static ConfigBuilder.BooleanValue vrEnabled; + public static ConfigBuilder.IntValue worldRotation; + public static ConfigBuilder.IntValue vrWorldRotationIncrement; + public static ConfigBuilder.IntValue worldScale; + public static ConfigBuilder.VectorValue originOffset; + public static ConfigBuilder.IntValue version; + public static ConfigBuilder.BooleanValue reverseHands; + public static ConfigBuilder.BooleanValue allowStandingOriginOffset; + public static ConfigBuilder.IntValue forceHardwareDetection; + public static ConfigBuilder.EnumValue stereoProviderPluginID; + public static ConfigBuilder.BooleanValue analogMovement; + public static ConfigBuilder.DoubleValue manualCalibration; + public static ConfigBuilder.EnumValue rightclickDelay; + public static ConfigBuilder.BooleanValue thirdPersonItems; + public static ConfigBuilder.BooleanValue bcbOn; //TODO rename shadow + public static ConfigBuilder.BooleanValue allowAdvancedBindings; + public static ConfigBuilder.DoubleValue xSensitivity; + public static ConfigBuilder.DoubleValue ySensitivity; + public static ConfigBuilder.DoubleValue keyholeX; + public static ConfigBuilder.BooleanValue useFsaa; + public static ConfigBuilder.BooleanValue displayMirrorLeftEye; + public static ConfigBuilder.BooleanValue disableFun; + public static ConfigBuilder.EnumValue menuWorldSelection; + public static ConfigBuilder.BooleanValue insideBlockSolidColor; + public static ConfigBuilder.EnumValue renderBlockOutlineMode; + public static ConfigBuilder.IntValue hrtfSelection; //TODO remove? + + + //Radial + public static ConfigBuilder.BooleanValue radialModeHold; + public static ConfigBuilder.ArrayValue main; + public static ConfigBuilder.ArrayValue alt; + + //QuickCommand + public static ConfigBuilder.ArrayValue commands; + + //FOV + public static ConfigBuilder.DoubleValue monoFOV; //TODO Dummy + public static ConfigBuilder.DoubleValue fovReductionMin; + public static ConfigBuilder.DoubleValue fovRedutioncOffset; //TODO typo + public static ConfigBuilder.BooleanValue fovReduction; + + private static CommentedFileConfig config; + private static ConfigBuilder builder; + + public static List getConfigValues(){ + return builder.getConfigValues(); + } + + public static ConfigBuilder.ConfigValue[] generalConfig() { + return new ConfigBuilder.ConfigValue[]{ + vrEnabled, + vrHotswitchingEnabled, + version, + worldScale, + worldRotation, + vrWorldRotationIncrement, + allowStandingOriginOffset, + originOffset, + forceHardwareDetection, + stereoProviderPluginID, + reverseHands, + analogMovement, + manualCalibration, + rightclickDelay, + thirdPersonItems, + bcbOn, + allowAdvancedBindings, + xSensitivity, + ySensitivity, + keyholeX, + useFsaa, + displayMirrorLeftEye, + disableFun, + menuWorldSelection, + insideBlockSolidColor, + renderBlockOutlineMode, + hrtfSelection + }; + } + + public static ConfigBuilder.ConfigValue[] keyboardConfig() { + return new ConfigBuilder.ConfigValue[]{ + physicalKeyboard, + autoOpenKeyboard, + alwaysSimulateKeyboard, + keyboardKeys, + keyboardKeysShift, + physicalKeyboardScale, + physicalKeyboardTheme + }; + } + + public static ConfigBuilder.ConfigValue[] mrConfig() { + return new ConfigBuilder.ConfigValue[]{ + mrMovingCamOffset, + mrMovingCamOffsetRot, + mixedRealityKeyColor, + mixedRealityAlphaMask, + mixedRealityFov, + mixedRealityRenderCameraModel, + mixedRealityUndistorted, + mixedRealityUnityLike, + mixedRealityRenderHands + }; + } + + public static ConfigBuilder.ConfigValue[] roomScaleConfig() { + return new ConfigBuilder.ConfigValue[]{ + realisticSneakEnabled, + sneakThreshold, + realisticJumpEnabled, + jumpThreshold, + autoSprint, + autoSprintThreshold, + allowCrawling, + crawlThreshold, + realisticClimbEnabled, + realisticRowEnabled, + realisticSwimEnabled, + movementSpeedMultiplier, + walkMultiplier, + weaponCollision, + bowMode, + walkUpBlocks, + backpackSwitching, + vrTouchHotbar, + guiAppearOverBlock, + physicalGuiEnabled, + inertiaFactor, + vehicleRotation + }; + } + + public static ConfigBuilder.ConfigValue[] displayConfig() { + return new ConfigBuilder.ConfigValue[]{ + displayMirrorMode, + useCrosshairOcclusion, + menuCrosshairScale, + crosshairScalesWithDistance, + menuBackground, + menuAlwaysFollowFace, + renderInGameCrosshairMode, + shaderGUIRender, + hideGUI, + crosshairScale, + renderScaleFactor + }; + } + + public static ConfigBuilder.ConfigValue[] hudConfig() { + return new ConfigBuilder.ConfigValue[]{ + lowHealthIndicator, + hudDistance, + hudPitchOffset, + hudYawOffset, + stencilOn, + headHudScale, + headToHmdLength, + hudOcclusion, + hudOpacity, + vrHudLockMode + }; + } + + public static ConfigBuilder.ConfigValue[] cameraConfig() { + return new ConfigBuilder.ConfigValue[]{ + handCameraResScale, + handCameraFov, + vrFixedCampos, + vrFixedCamrot, + externalCameraAngleOrder + }; + } + + public static ConfigBuilder.ConfigValue[] updateConfig() { + return new ConfigBuilder.ConfigValue[]{ + firstRun, + lastUpdate, + alwaysShowUpdates, + chatNotifications, + showServerPluginMessage, + chatNotificationSound + }; + } + + public static ConfigBuilder.ConfigValue[] teleportConfig() { + return new ConfigBuilder.ConfigValue[]{ + limitedTeleport, + teleportLimitDown, + teleportLimitHoriz, + teleportLimitUp + }; + } + + public static ConfigBuilder.ConfigValue[] seatedConfig() { + return new ConfigBuilder.ConfigValue[]{ + seated, + seatedhmd, + seatedHudAltMode, + seatedFreeMove, + forceStandingFreeMove, + vrFreeMoveFlyMode, + vrFreeMoveMode + }; + } + + public static ConfigBuilder.ConfigValue[] fovConfig() { + return new ConfigBuilder.ConfigValue[]{ + monoFOV, + fovReductionMin, + fovRedutioncOffset, + fovReduction + }; + } + + public static void init(ConfigSpec.CorrectionListener listener){ + Config.setInsertionOrderPreserved(true); + config = CommentedFileConfig + .builder(Xplat.getConfigPath("vivecraft-client-config.toml")) + .autosave() + .concurrent() + .build(); + + config.load(); + + if (listener == null) { + listener = (action, path, incorrectValue, correctedValue) -> { + if (incorrectValue != null) { + System.out.println("Corrected " + String.join(".", path) + ": was " + incorrectValue + ", is now " + correctedValue); + } + }; + } + + fixConfig(config, listener); + + config.save(); + } + + private static void fixConfig(CommentedConfig config, ConfigSpec.CorrectionListener listener) { + + builder = new ConfigBuilder(config, new ConfigSpec()); + + builder.push("general"); + vrEnabled = builder + .push("vrEnabled") + .comment("Enable VR") + .define(false); + vrHotswitchingEnabled = builder + .push("hotswitch") + .comment("Allow hotswitch between VR and nonVR") + .define(true); + version = builder + .push("version") + .comment("Compatibility version used on servers") + .defineInRange(0, 0, 0); + worldScale = builder + .push("worldscale") + .comment("") + .defineInRange(1,0, 29); + worldRotation = builder + .push("worldrotation") + .comment("") + .defineInRange(0,0, 360); + vrWorldRotationIncrement = builder + .push("vrWorldRotationIncrement") + .comment("") + .defineInRange(45,0, 180); + allowStandingOriginOffset = builder + .push("allowStandingOriginOffset") + .comment("") + .define(false); + originOffset = builder + .push("originOffset") + .comment("") + .define(new Vector3f( 0f, 0f, 0f)); + forceHardwareDetection = builder + .push("forceHardwareDetection") + .comment("0 = off, 1 = vive, 2 = oculus") //TODO enum? + .defineInRange(0, 0,2); + stereoProviderPluginID = builder + .push("stereoProviderPluginID") + .comment("") + .define(VRSettings.VRProvider.OPENVR); + reverseHands = builder + .push("reverseHands") + .comment("Change the main hand to left") + .define(false); + analogMovement = builder + .push("analogMovement") + .comment("") + .define(true); + manualCalibration = builder + .push("manualCalibration") + .comment("") + .defineInRange(-1.0d, -1.0d, 5.0d); //TODO check + rightclickDelay = builder + .push("rightclickDelay") + .comment("") + .define(VRSettings.RightClickDelay.VANILLA); + thirdPersonItems = builder + .push("thirdPersonItems") + .comment("") + .define(false); + bcbOn = builder + .push("bcbOn") + .comment("") + .define(true); + allowAdvancedBindings = builder + .push("allowAdvancedBindings") + .comment("") + .define(false); + xSensitivity = builder + .push("xSensitivity") + .comment("") + .defineInRange(1d, 0.1d, 5d); + ySensitivity = builder + .push("ySensitivity") + .comment("") + .defineInRange(1d, 0.1d, 5d); + keyholeX = builder + .push("keyholeX") + .comment("") + .defineInRange(15d, 0d, 40d); + useFsaa = builder + .push("fsaa") + .comment("Enable FSAA") + .define(false); + disableFun = builder + .push("disableFun") + .comment("") + .define(false); + menuWorldSelection = builder + .push("menuWorldSelection") + .comment("") + .define(VRSettings.MenuWorld.BOTH); + insideBlockSolidColor = builder + .push("insideblock") + .comment("If the the inside of a block should be solid black") + .define(false); + renderBlockOutlineMode = builder + .push("renderBlockOutlineMode") + .comment("") + .define(VRSettings.RenderPointerElement.ALWAYS); + displayMirrorLeftEye = builder + .push("lefteye") + .comment("Use the left eye instead of the right eye for the mirror") + .define(false); + hrtfSelection = builder + .push("hrtfSelection") + .comment("") + .defineInRange(0, -1, 0); + builder.pop(); + + builder + .push("keyboard"); + physicalKeyboard = builder + .push("physical") + .comment("Enables the Physical Keyboard") + .define(true); + autoOpenKeyboard = builder + .push("open") + .comment("Automatically open the keyboard") + .define(false); + alwaysSimulateKeyboard = builder + .push("simulate") + .comment("Always simulate the Keyboard") + .define(false); + keyboardKeys = builder + .push("keys") + .comment("Keyboard key Layout") + .define("`1234567890-=qwertyuiop[]\\asdfghjkl;':\"zxcvbnm,./?<>"); + keyboardKeysShift = builder + .push("shiftkeys") + .comment("Keyboard key Layout for shift") + .define("~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL;':\\\"ZXCVBNM,./?<>"); + physicalKeyboardScale = builder + .push("scale") + .comment("The scale for the Physical Keyboard") + .defineInRange(1.0d, 0.75d, 1.5d); + physicalKeyboardTheme = builder + .push("theme") + .comment("Keyboard theme used for the Physical Keyboard") + .define(PhysicalKeyboard.KeyboardTheme.DEFAULT); + builder.pop(); + + builder.push("roomscale"); + realisticSneakEnabled = builder + .push("sneak") + .comment("Enable room scale sneaking") + .define(true); + sneakThreshold = builder + .push("sneakthreshold") + .comment("Threshold for when the player starts sneaking") + .defineInRange(0.4, 0, 2); //2 should be enough range + realisticJumpEnabled = builder + .push("jump") + .comment("Enable room scale jumping") + .define(true); + jumpThreshold = builder + .push("jumpthreshhold") + .comment("Threshhold for automatically jumping") + .defineInRange(0.05d, 0d, 2d); //2 should be enough + autoSprint = builder + .push("sprint") + .comment("Automatically sprint") + .define(true); + autoSprintThreshold = builder + .push("sprintthreshhold") + .comment("Threshhold for automatically sprinting") + .defineInRange(0.9d, 0.5d, 1d); + allowCrawling = builder + .push("crawl") + .comment("Enable room scale crawling") + .define(true); + crawlThreshold = builder + .push("crawlthreshold") + .comment("Threshold for when the player starts crawling") + .defineInRange(0.82, 0, 2); //2 should be enough range + weaponCollision = builder + .push("weaponcollision") + .comment("Weapon Collision mode used") + .define(VRSettings.WeaponCollision.AUTO); + bowMode = builder + .push("bow") + .comment("Bow mode") + .define(VRSettings.BowMode.ON); + vrTouchHotbar = builder + .push("hotbar") + .comment("Allow selecting items from by touching the hotbar") + .define(true); + physicalGuiEnabled = builder + .push("gui") + .comment("Allow interactions by touching the gui") + .define(true); + realisticRowEnabled = builder + .push("row") + .comment("Enable room scale rowing") + .define(true); + realisticClimbEnabled = builder + .push("climbing") + .comment("Enable room scale climbing") + .define(true); + realisticSwimEnabled = builder + .push("swimming") + .comment("Enable room scale swimming") + .define(true); + guiAppearOverBlock = builder + .push("guiblock") + .comment("Places the gui over the accessed block") + .define(true); + movementSpeedMultiplier = builder + .push("movementspeed") + .comment("Movement Speed modifier") + .defineInRange(1.0d, 0.15d, 1.3d); + walkMultiplier = builder + .push("walkspeed") + .comment("Walk Speed modifier") + .defineInRange(1.0d, 1d, 10d); + backpackSwitching = builder + .push("backpack") + .comment("Enables backpack switching") + .define(true); + walkUpBlocks = builder + .push("walkup") + .comment("Enable auto step up") + .define(true); + inertiaFactor = builder + .push("inertia") + .comment("The inertia") + .define(VRSettings.InertiaFactor.NORMAL); + vehicleRotation = builder + .push("vehicleRotation") + .comment("Rotate vehicles") + .define(true); + builder.pop(); + + builder.push("seated"); + seated = builder + .push("enable") + .comment("Enables seated mode") + .define(false); + seatedhmd = builder + .push("hmd") + .comment("") + .define(false); + seatedHudAltMode = builder + .push("altmode") + .comment("Enables the alternative HUD position when playing as seated") + .define(false); + seatedFreeMove = builder + .push("freemove") + .comment("Allow free move while playing as seated") + .define(true); + forceStandingFreeMove = builder + .push("forceStandingFreeMove") + .comment("") + .define(false); + vrFreeMoveMode = builder + .push("vrFreeMoveMode") + .comment("Movement mode when using free move") + .define(VRSettings.FreeMove.CONTROLLER); + vrFreeMoveFlyMode = builder + .push("vrFreeMoveFlyMode") + .comment("Movement mode when flying in free move") + .define(VRSettings.FreeMove.AUTO); + builder.pop(); + + builder.push("display"); + useCrosshairOcclusion = builder + .push("crosshairocclusion") + .comment("Occludes the crosshair") + .define(true); + displayMirrorMode = builder + .push("mirror") + .comment("Mirror mode") + .define(VRSettings.MirrorMode.SINGLE); + renderScaleFactor = builder + .push("scale") + .comment("The scale used to render") + .defineInRange(1.0d, 0.1d, 9d); + shaderGUIRender = builder + .push("shaders") + .comment("Changes how shaders are applied on GUI's") + .define(VRSettings.ShaderGUIRender.AFTER_SHADER); + hideGUI = builder //TODO remove as it is a dummy storage field + .push("hide") + .comment("Hides the gui") + .define(false); + menuAlwaysFollowFace = builder + .push("followface") + .comment("Makes the menu follow the players head") + .define(false); + menuCrosshairScale = builder + .push("menuCrosshairScale") + .comment("The scale for the crosshair in the menus") + .defineInRange(1.0d, 0.25d, 2.5d); + crosshairScalesWithDistance = builder + .push("crosshairScalesWithDistance") + .comment("Scale for the crosshair with distance") + .define(false); + menuBackground = builder + .push("menuBackground") + .comment("Use a background in menus") + .define(false); + renderInGameCrosshairMode = builder + .push("renderInGameCrosshairMode") + .comment("The style of the crosshair") + .define(VRSettings.RenderPointerElement.ALWAYS); + crosshairScale = builder + .push("crosshairScale") + .comment("The scale of the crosshair") + .defineInRange(1.0d, 0.25d, 1.0d); + builder.pop(); + + builder.push("hud"); + vrHudLockMode = builder + .push("hudlock") + .comment("Determines where the hotbar is locked") + .define(VRSettings.HUDLock.HEAD); + lowHealthIndicator = builder + .push("health") + .comment("Enables the flashing of red on screen when on low health") + .define(true); + hudDistance = builder + .push("hud") + .comment("The distance between the player and the HUD") + .defineInRange(1.25d, 0.25d, 5.0d); + hudPitchOffset = builder + .push("hudpitch") + .comment("The pitch offset of the hud") + .defineInRange(-2.0d, -5d,5d); //TODO what limit is fine here? int.max seems to much? + hudYawOffset = builder + .push("hudyaw") + .comment("The yaw offset of the hud") + .defineInRange(0.0d, -5d,5d); //TODO what limit is fine here? int.max seems to much? + headHudScale = builder + .push("hudscale") + .comment("The scale of the hud") + .defineInRange(1.0d, 0.35d, 2.5d); + hudOpacity = builder + .push("hudopacity") + .comment("The opacity of the hud") + .defineInRange(1.0d, 0.15d, 1.0d); + hudOcclusion = builder + .push("hudOcclusion") + .comment("Should the hud use occlusion") + .define(true); + stencilOn = builder + .push("stencil") + .comment("Enables the eye stencil") + .define(true); + headToHmdLength = builder + .push("hmdhead") + .comment("The distance between the head and the hmd") + .defineInRange(0.10d, 0d, 1.0d); + builder.pop(); + + builder.push("fov"); + monoFOV = builder + .push("monoFOV") + .comment("") + .defineInRange(0.0d, 0d, 1.0d); + fovReduction = builder + .push("fovReduction") + .comment("") + .define(false); + fovReductionMin = builder + .push("fovReductionMin") + .comment("") + .defineInRange(0.25d, 0.1d, 0.7d); + fovRedutioncOffset = builder + .push("fovReductionOffset") + .comment("") + .defineInRange(0.1d,0d, 0.3d); + builder.pop(); + + builder.push("camera"); + handCameraResScale = builder + .push("resolution") + .comment("") + .defineInRange(1.0d, 0.5d, 3.0d); + handCameraFov = builder + .push("fov") + .comment("") + .defineInRange(70, 1, 179); + vrFixedCampos = builder + .push("vrFixedCampos") + .comment("") + .define(new Vector3f(-1.0f, 2.4f, 2.7f)); + vrFixedCamrot = builder + .push("vrFixedCamrot") + .comment("") + .define(new Quaternionf(.962f, .125f, .239f, .041f)); + externalCameraAngleOrder = builder + .push("externalCameraAngleOrder") + .comment("") + .define(Angle.Order.XYZ); + builder.pop(); + + builder.push("update"); + firstRun = builder + .push("firstRun") + .comment("Is this the first time the game is run") + .define(true); //TODO remove? + lastUpdate = builder + .push("lastUpdate") + .comment("the latest version available") + .define(""); + alwaysShowUpdates = builder + .push("alwaysShowUpdates") + .comment("Show that updates are possible on each restart") + .define(true); + showServerPluginMessage = builder + .push("showServerPluginMessage") + .comment("Show messages from the server side plugin") + .define(true); + chatNotifications = builder + .push("chatNotifications") + .comment("Should messages in chat notify the player") + .define(VRSettings.ChatNotifications.NONE); + chatNotificationSound = builder + .push("chatNotificationSound") + .comment("The sound used for chat notifications") + .define("block.note_block.bell"); + builder.pop(); + + builder.push("teleport"); + limitedTeleport = builder + .push("limitedTeleport") + .comment("Limit teleportation") + .define(false); + teleportLimitUp = builder + .push("teleportLimitUp") + .comment("Limit for upwards teleportation") + .defineInRange(1,0,4); + teleportLimitDown = builder + .push("teleportLimitDown") + .comment("Limit for downwards teleportation") + .defineInRange(4,0, 16); + teleportLimitHoriz = builder + .push("teleportLimitHoriz") + .comment("Limit for side teleportation") + .defineInRange(16,0, 32); + builder.pop(); + + builder.push("radial"); + radialModeHold = builder + .push("radialModeHold") + .comment("") + .define(false); + main = builder + .push("main") + .define(getRadialItemsDefault(), String.class, s -> s); + alt = builder + .push("alt") + .define(getRadialItemsAltDefault(), String.class, s -> s); + builder.pop(); + + builder.push("quickcommands"); + commands = builder + .push("commands") + .define(getQuickCommandsDefaults(), String.class, s -> s); + builder.pop(); + + builder.push("mixedReality"); + mrMovingCamOffset = builder + .push("mrMovingCamOffset") + .comment("") + .define(new Vector3f(0f, 0f, 0f)); + mrMovingCamOffsetRot = builder + .push("mrMovingCamOffsetRot") + .comment("") + .define(new Quaternionf()); + mixedRealityKeyColor = builder + .push("mixedRealityKeyColor") + .comment("") + .define("#000000"); + mixedRealityAlphaMask = builder + .push("mixedRealityAlphaMask") + .comment("") + .define(false); + mixedRealityFov = builder + .push("mixedRealityFov") + .comment("") + .defineInRange(40, 0, 179); + mixedRealityRenderCameraModel = builder + .push("mixedRealityRenderCameraModel") + .comment("") + .define(true); + mixedRealityUndistorted = builder + .push("mixedRealityUndistorted") + .comment("") + .define(true); + mixedRealityUnityLike = builder + .push("mixedRealityUnityLike") + .comment("") + .define(true); + mixedRealityRenderHands = builder + .push("mixedRealityRenderHands") + .comment("") + .define(false); + builder.pop(); + + builder.correct(listener); + + } + + public static String[] getRadialItemsDefault(){ + String[] out = new String[8]; + out[0] = "key.drop"; + out[1] = "key.chat"; + out[2] = "vivecraft.key.rotateRight"; + out[3] = "key.pickItem"; + out[4] = "vivecraft.key.toggleHandheldCam"; + out[5] = "vivecraft.key.togglePlayerList"; + out[6] = "vivecraft.key.rotateLeft"; + out[7] = "vivecraft.key.quickTorch"; + + return out; + } + + public static String[] getRadialItemsAltDefault(){ + String[] out = new String[8]; + out[0] = ""; + out[1] = ""; + out[2] = ""; + out[3] = ""; + out[4] = ""; + out[5] = ""; + out[6] = ""; + out[7] = ""; + + return out; + } + + public static String[] getQuickCommandsDefaults(){ + + String[] out = new String[12]; + out[0] = "/gamemode survival"; + out[1] = "/gamemode creative"; + out[2] = "/help"; + out[3] = "/home"; + out[4] = "/sethome"; + out[5] = "/spawn"; + out[6] = "hi!"; + out[7] = "bye!"; + out[8] = "follow me!"; + out[9] = "take this!"; + out[10] = "thank you!"; + out[11] = "praise the sun!"; + + return out; + + } +} diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiArrayValueEditScreen.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiArrayValueEditScreen.java new file mode 100644 index 000000000..c00620071 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiArrayValueEditScreen.java @@ -0,0 +1,121 @@ +package org.vivecraft.client.gui.settings; + +import com.google.common.collect.ImmutableList; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.narration.NarratableEntry; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import org.vivecraft.client.gui.widgets.SettingsList; +import org.vivecraft.common.ConfigBuilder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.function.BooleanSupplier; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class GuiArrayValueEditScreen extends GuiListScreen{ + private final ConfigBuilder.ArrayValue arrayValue; + private final Function fromString; + private T[] elements; + + public GuiArrayValueEditScreen(Component title, Screen lastScreen, ConfigBuilder.ArrayValue arrayValue, Function fromString) { + super(title, lastScreen); + this.arrayValue = arrayValue; + this.fromString = fromString; + } + + @Override + protected void init() { + clearWidgets(); + double scrollAmount = list != null? list.getScrollAmount() : 0.0D; + + this.list = new SettingsList(this, minecraft, getEntries()); + list.setScrollAmount(scrollAmount); + this.addWidget(this.list); + + this.addRenderableWidget(Button.builder(CommonComponents.GUI_DONE, button -> { + arrayValue.set(getCurrentValues()); + this.minecraft.setScreen(this.lastScreen); + }).bounds(this.width / 2 - 155, this.height - 27, 150, 20).build()); + + this.addRenderableWidget(Button + .builder(CommonComponents.GUI_CANCEL, button -> this.minecraft.setScreen(this.lastScreen)) + .bounds(this.width / 2 + 5, this.height - 27, 150, 20) + .build()); + } + + @Override + protected List getEntries() { + List entries = new LinkedList<>(); + if (elements == null) { + elements = Arrays.copyOf(arrayValue.get(), arrayValue.get().length); + } + int i = 0; + for (T item : elements) { + EditBox box = new EditBox(Minecraft.getInstance().font, 0, 0, ArrayResetEntry.valueButtonWidth - 1, 20, Component.literal(item + "")); + box.setMaxLength(1000); + box.setValue(item + ""); + int index = i++; + entries.add(new ArrayResetEntry(Component.empty(), box, () -> !fromString.apply(box.getValue()).equals(arrayValue.getDefault()[index]), button -> {elements[index] = arrayValue.getDefault()[index];reinit = true;})); + } + return entries; + } + + private T[] getCurrentValues(){ + return (T[]) list.children().stream().map(entry -> { + if (entry instanceof ArrayResetEntry arrayResetEntry) { + return fromString.apply(arrayResetEntry.getString()); + } else { + return fromString.apply(""); + } + }).collect(Collectors.toList()).toArray(); + } + + private static class ArrayResetEntry extends SettingsList.WidgetEntry { + public static final int valueButtonWidth = 280; + private final BooleanSupplier canReset; + private final Button resetButton; + + public ArrayResetEntry(Component name, EditBox valueWidget, BooleanSupplier canReset, Button.OnPress resetAction) { + super(name, valueWidget); + this.canReset = canReset; + + this.resetButton = Button.builder(Component.literal("X"), resetAction) + .tooltip(Tooltip.create(Component.translatable("controls.reset"))) + .bounds(0, 0, 20, 20).build(); + } + + @Override + public void render(GuiGraphics guiGraphics, int i, int j, int k, int l, int m, int n, int o, boolean bl, float f) { + this.valueWidget.setX(k - 50); + this.valueWidget.setY(j); + this.valueWidget.render(guiGraphics, n, o, f); + this.resetButton.setX(k + 230); + this.resetButton.setY(j); + this.resetButton.active = canReset.getAsBoolean(); + this.resetButton.render(guiGraphics, n, o, f); + } + + @Override + public List children() { + return ImmutableList.of(this.valueWidget, this.resetButton); + } + + @Override + public List narratables() { + return ImmutableList.of(this.valueWidget, this.resetButton); + } + + public String getString() { + return ((EditBox)valueWidget).getValue(); + } + } +} diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiClientSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiClientSettings.java new file mode 100644 index 000000000..e153e971b --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiClientSettings.java @@ -0,0 +1,33 @@ +package org.vivecraft.client.gui.settings; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.vivecraft.client.ClientConfig; +import org.vivecraft.client.gui.widgets.SettingsList; +import org.vivecraft.common.ConfigBuilder; + +import java.util.LinkedList; +import java.util.List; + +public class GuiClientSettings extends GuiListScreen { + public GuiClientSettings(Screen lastScreen) { + super(Component.translatable("vivecraft.options.screen.client"), lastScreen); + } + + @Override + protected List getEntries() { + List entries = new LinkedList<>(); + String lastCategory = null; + for (ConfigBuilder.ConfigValue cv : ClientConfig.getConfigValues()) { + String path = cv.getPath(); + String category = path.substring(0, path.lastIndexOf(".")); + String name = path.substring(path.lastIndexOf(".") + 1); + if (!category.equals(lastCategory)) { + lastCategory = category; + entries.add(new SettingsList.CategoryEntry(Component.literal(category))); + } + entries.add(SettingsList.ConfigToEntry(cv, Component.literal(name))); + } + return entries; + } +} diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiConfigListScreen.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiConfigListScreen.java new file mode 100644 index 000000000..9d35b30a1 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiConfigListScreen.java @@ -0,0 +1,29 @@ +package org.vivecraft.client.gui.settings; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.vivecraft.client.gui.widgets.SettingsList; +import org.vivecraft.common.ConfigBuilder; + +import java.util.LinkedList; +import java.util.List; + +public class GuiConfigListScreen extends GuiListScreen{ + private final ConfigBuilder.ConfigValue[] config; + + public GuiConfigListScreen(Component title, Screen lastScreen, ConfigBuilder.ConfigValue ... config) { + super(title, lastScreen); + this.config = config; + } + + @Override + protected List getEntries() { + List entries = new LinkedList<>(); + for (ConfigBuilder.ConfigValue value : config) { + String path = value.getPath(); + String name = path.substring(path.lastIndexOf(".") + 1); + entries.add(SettingsList.ConfigToEntry(value, Component.literal(name))); + } + return entries; + } +} diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiListValueEditScreen.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiListValueEditScreen.java index ee41c33aa..61d38d14b 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiListValueEditScreen.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiListValueEditScreen.java @@ -12,7 +12,7 @@ import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import org.vivecraft.client.gui.widgets.SettingsList; -import org.vivecraft.server.config.ConfigBuilder; +import org.vivecraft.common.ConfigBuilder; import java.util.ArrayList; import java.util.LinkedList; @@ -100,7 +100,7 @@ public ListValueEntry(Component name, EditBox valueWidget, Button.OnPress delete @Override public void render(GuiGraphics guiGraphics, int i, int j, int k, int l, int m, int n, int o, boolean bl, float f) { - this.valueWidget.setX(k + -50); + this.valueWidget.setX(k - 50); this.valueWidget.setY(j); this.valueWidget.render(guiGraphics, n, o, f); this.deleteButton.setX(k + 230); diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java index 209a37852..f3a73ebdb 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiServerSettings.java @@ -3,8 +3,8 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import org.vivecraft.client.gui.widgets.SettingsList; -import org.vivecraft.server.config.ConfigBuilder; -import org.vivecraft.server.config.ServerConfig; +import org.vivecraft.common.ConfigBuilder; +import org.vivecraft.server.ServerConfig; import java.util.LinkedList; import java.util.List; diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java index c8f8bd465..81a5bc47f 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/VivecraftMainSettings.java @@ -7,6 +7,7 @@ import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import org.vivecraft.client.ClientConfig; import org.vivecraft.client.gui.widgets.SettingsList; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.ClientDataHolderVR; @@ -47,6 +48,10 @@ protected List getEntries() { Component.translatable("vivecraft.options.screen.server"), Button.builder(Component.translatable("vivecraft.options.screen.server"), button -> this.minecraft.setScreen(new GuiServerSettings(this))).size(SettingsList.WidgetEntry.valueButtonWidth, 20).build())); + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.client"), + Button.builder(Component.translatable("vivecraft.options.screen.client"), button -> this.minecraft.setScreen(new GuiClientSettings(this))).size(SettingsList.WidgetEntry.valueButtonWidth, 20).build())); + entries.add(new SettingsList.CategoryEntry(Component.literal("Vivecraft Buttons"))); entries.add(new SettingsList.WidgetEntry( @@ -55,18 +60,99 @@ protected List getEntries() { ClientDataHolderVR.getInstance().vrSettings.vrToggleButtonEnabled = !ClientDataHolderVR.getInstance().vrSettings.vrToggleButtonEnabled; ClientDataHolderVR.getInstance().vrSettings.saveOptions(); }))); + entries.add(new SettingsList.WidgetEntry( Component.translatable("vivecraft.options.VR_SETTINGS_BUTTON_VISIBLE"), CycleButton.onOffBuilder(ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonEnabled).displayOnlyValue().create(0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, Component.empty(), (cycleButton, object) -> { ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonEnabled = !ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonEnabled; ClientDataHolderVR.getInstance().vrSettings.saveOptions(); }))); + entries.add(new SettingsList.WidgetEntry( Component.translatable("vivecraft.options.VR_SETTINGS_BUTTON_POSITION"), new CycleButton.Builder(bool -> bool ? Component.translatable("vivecraft.options.left") : Component.translatable("vivecraft.options.right")).withValues(ImmutableList.of(Boolean.TRUE, Boolean.FALSE)).withInitialValue(ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonPositionLeft).displayOnlyValue().create(0, 0, SettingsList.WidgetEntry.valueButtonWidth, 20, Component.empty(), (cycleButton, object) -> { ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonPositionLeft = !ClientDataHolderVR.getInstance().vrSettings.vrSettingsButtonPositionLeft; ClientDataHolderVR.getInstance().vrSettings.saveOptions(); }))); + + entries.add(new SettingsList.CategoryEntry(Component.literal("Client Settings"))); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.general"), + Button.builder(Component.translatable("vivecraft.options.screen.general"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.general"), this, ClientConfig.generalConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.update"), + Button.builder(Component.translatable("vivecraft.options.screen.update"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.update"), this, ClientConfig.updateConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.roomscale"), + Button.builder(Component.translatable("vivecraft.options.screen.roomscale"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.roomscale"), this, ClientConfig.roomScaleConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.seated"), + Button.builder(Component.translatable("vivecraft.options.screen.seated"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.seated"), this, ClientConfig.seatedConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.teleport"), + Button.builder(Component.translatable("vivecraft.options.screen.teleport"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.teleport"), this, ClientConfig.teleportConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.display"), + Button.builder(Component.translatable("vivecraft.options.screen.display"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.display"), this, ClientConfig.displayConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.hud"), + Button.builder(Component.translatable("vivecraft.options.screen.hud"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.hud"), this, ClientConfig.hudConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.fov"), + Button.builder(Component.translatable("vivecraft.options.screen.fov"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.fov"), this, ClientConfig.fovConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.camera"), + Button.builder(Component.translatable("vivecraft.options.screen.camera"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.camera"), this, ClientConfig.cameraConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.mr"), + Button.builder(Component.translatable("vivecraft.options.screen.mr"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.mr"), this, ClientConfig.mrConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.WidgetEntry( + Component.translatable("vivecraft.options.screen.keyboard"), + Button.builder(Component.translatable("vivecraft.options.screen.keyboard"), button -> this.minecraft.setScreen(new GuiConfigListScreen(Component.translatable("vivecraft.options.screen.keyboard"), this, ClientConfig.keyboardConfig()))) + .size(SettingsList.WidgetEntry.valueButtonWidth, 20) + .build())); + + entries.add(new SettingsList.CategoryEntry(Component.literal("Radial"))); + + entries.add(SettingsList.ConfigToEntry(ClientConfig.radialModeHold, Component.literal(ClientConfig.radialModeHold.getPath()))); + entries.add(SettingsList.ConfigToEntry(ClientConfig.main, Component.literal(ClientConfig.main.getPath()))); + entries.add(SettingsList.ConfigToEntry(ClientConfig.alt, Component.literal(ClientConfig.alt.getPath()))); + + entries.add(new SettingsList.CategoryEntry(Component.literal("Quick Commands"))); + + entries.add(SettingsList.ConfigToEntry(ClientConfig.commands, Component.literal(ClientConfig.commands.getPath()))); + return entries; } } diff --git a/common/src/main/java/org/vivecraft/client/gui/widgets/QuadWidget.java b/common/src/main/java/org/vivecraft/client/gui/widgets/QuadWidget.java new file mode 100644 index 000000000..db8e4c261 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/gui/widgets/QuadWidget.java @@ -0,0 +1,174 @@ +package org.vivecraft.client.gui.widgets; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import org.joml.Quaternionf; +import org.vivecraft.common.ConfigBuilder; + +import java.util.function.Consumer; + +public class QuadWidget extends AbstractWidget { + + private final NumberEditBox xBox; + private final NumberEditBox yBox; + private final NumberEditBox zBox; + private final NumberEditBox wBox; + + public QuadWidget(int i, int j, int k, int l, Component component, ConfigBuilder.QuatValue value) { + super(i, j, k, l, component); + Quaternionf quaternionf = value.get(); + this.xBox = new NumberEditBox(Minecraft.getInstance().font, i , j, (k-4) / 4, l , Component.literal(quaternionf.x +""), quaternionf.x, d -> value.set(new Quaternionf(d, quaternionf.y, quaternionf.z, quaternionf.w))); + this.yBox = new NumberEditBox(Minecraft.getInstance().font, i + ((k - 4) / 4) + 1, j, (k-4) / 4, l , Component.literal(quaternionf.y +""), quaternionf.y, d -> value.set(new Quaternionf(quaternionf.x, d, quaternionf.z, quaternionf.w))); + this.zBox = new NumberEditBox(Minecraft.getInstance().font, i + ((k-4) / 4)*2 + 2, j, (k-4) / 4, l , Component.literal(quaternionf.z +""), quaternionf.z, d -> value.set(new Quaternionf(quaternionf.x, quaternionf.y, d, quaternionf.w))); + this.wBox = new NumberEditBox(Minecraft.getInstance().font, i + ((k-4) / 4)*3 + 3, j, (k-4) / 4, l , Component.literal(quaternionf.w +""), quaternionf.w, d -> value.set(new Quaternionf(quaternionf.x, quaternionf.y, quaternionf.z, d))); + + } + + @Override + public void render(GuiGraphics guiGraphics, int i, int j, float f) { + this.xBox.render(guiGraphics, i, j, f); + this.yBox.render(guiGraphics, i, j, f); + this.zBox.render(guiGraphics, i, j, f); + this.wBox.render(guiGraphics, i, j, f); + + } + + @Override + protected void renderWidget(GuiGraphics guiGraphics, int i, int j, float f) { + this.xBox.renderWidget(guiGraphics, i, j, f); + this.yBox.renderWidget(guiGraphics, i, j, f); + this.zBox.renderWidget(guiGraphics, i, j, f); + this.wBox.renderWidget(guiGraphics, i, j, f); + } + + @Override + public void renderTexture(GuiGraphics guiGraphics, ResourceLocation resourceLocation, int i, int j, int k, int l, int m, int n, int o, int p, int q) { + this.xBox.renderTexture(guiGraphics, resourceLocation, i, j, k, l, m, n, o, p, q); + this.yBox.renderTexture(guiGraphics, resourceLocation, i, j, k, l, m, n, o, p, q); + this.zBox.renderTexture(guiGraphics, resourceLocation, i, j, k, l, m, n, o, p, q); + this.wBox.renderTexture(guiGraphics, resourceLocation, i, j, k, l, m, n, o, p, q); + } + + @Override + public void setX(int i) { + super.setX(i); + this.xBox.setX(i); + this.yBox.setX(i + (width-4)/4 + 1); + this.zBox.setX(i + ((width-4)/4)*2 + 2); + this.wBox.setX(i + ((width-4)/4)*3 + 3); + } + + @Override + public void setY(int i) { + super.setY(i); + this.xBox.setY(i); + this.yBox.setY(i); + this.zBox.setY(i); + this.wBox.setY(i); + } + + @Override + public void setFocused(boolean bl) { + super.setFocused(bl); + this.xBox.setFocused(this.xBox.isHovered()); + this.yBox.setFocused(this.yBox.isHovered()); + this.zBox.setFocused(this.zBox.isHovered()); + this.wBox.setFocused(this.wBox.isHovered()); + + + } + + @Override + public boolean mouseClicked(double d, double e, int i) { + if (xBox.isMouseOver(d, e)) { + this.xBox.setFocused(true); + return this.xBox.mouseClicked(d,e,i); + } + if (yBox.isMouseOver(d, e)) { + this.yBox.setFocused(true); + return this.yBox.mouseClicked(d,e,i); + } + if (zBox.isMouseOver(d, e)) { + this.zBox.setFocused(true); + return this.zBox.mouseClicked(d,e,i); + } + if (wBox.isMouseOver(d, e)) { + this.wBox.setFocused(true); + return this.wBox.mouseClicked(d,e,i); + } + return super.mouseClicked(d, e, i); + } + + @Override + public boolean keyPressed(int i, int j, int k) { + if (this.xBox.isFocused()) { + return this.xBox.keyPressed(i, j, k); + } + if (this.yBox.isFocused()) { + return this.yBox.keyPressed(i, j, k); + } + if (this.zBox.isFocused()) { + return this.zBox.keyPressed(i, j, k); + } + if (this.wBox.isFocused()) { + return this.wBox.keyPressed(i, j, k); + } + return super.keyPressed(i, j, k); + } + + @Override + public boolean charTyped(char c, int i) { + if (this.xBox.isFocused()) { + return this.xBox.charTyped(c, i); + } + if (this.yBox.isFocused()) { + return this.yBox.charTyped(c, i); + } + if (this.zBox.isFocused()) { + return this.zBox.charTyped(c, i); + } + if (this.wBox.isFocused()) { + return this.wBox.charTyped(c, i); + } + return super.charTyped(c, i); + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) { + + } + + public static class NumberEditBox extends EditBox { + + private final Consumer floatConsumer; + + public NumberEditBox(Font font, int i, int j, int k, int l, Component component, float floatValue, Consumer floatConsumer) { + super(font, i, j, k, l, component); + this.floatConsumer = floatConsumer; + this.setValue(floatValue + ""); + } + + @Override + public boolean charTyped(char c, int i) { + if (c != 46 && (c < 48 || c > 57)) { + return false; + } + boolean ret = super.charTyped(c, i); + floatConsumer.accept(Float.valueOf(this.getValue())); + return ret; + } + + @Override + public boolean keyPressed(int i, int j, int k) { + boolean ret = super.keyPressed(i, j, k); + floatConsumer.accept(Float.valueOf(this.getValue())); + return ret; + } + } +} diff --git a/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java b/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java index fa7870a56..c717138f6 100644 --- a/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java +++ b/common/src/main/java/org/vivecraft/client/gui/widgets/SettingsList.java @@ -16,12 +16,11 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; -import org.vivecraft.server.config.ConfigBuilder; +import org.vivecraft.common.ConfigBuilder; import java.util.Collections; import java.util.List; import java.util.function.BooleanSupplier; -import java.util.function.Supplier; public class SettingsList extends ContainerObjectSelectionList { final Screen parent; diff --git a/common/src/main/java/org/vivecraft/client/gui/widgets/VectorWidget.java b/common/src/main/java/org/vivecraft/client/gui/widgets/VectorWidget.java new file mode 100644 index 000000000..8c9b341dc --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/gui/widgets/VectorWidget.java @@ -0,0 +1,119 @@ +package org.vivecraft.client.gui.widgets; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import org.joml.Vector3f; +import org.vivecraft.common.ConfigBuilder; + +public class VectorWidget extends AbstractWidget { + private final QuadWidget.NumberEditBox xBox; + private final QuadWidget.NumberEditBox yBox; + private final QuadWidget.NumberEditBox zBox; + + public VectorWidget(int i, int j, int k, int l, Component component, ConfigBuilder.VectorValue value) { + super(i, j, k, l, component); + Vector3f vector = value.get(); + this.xBox = new QuadWidget.NumberEditBox(Minecraft.getInstance().font, i , j, (k-3) / 3, l , Component.literal(vector.x +""), vector.x, d -> value.set(new Vector3f(d, vector.y, vector.z))); + this.yBox = new QuadWidget.NumberEditBox(Minecraft.getInstance().font, i + ((k - 3) / 3) + 1, j, (k-3) / 3, l , Component.literal(vector.y +""), vector.y, d -> value.set(new Vector3f(vector.x, d, vector.z))); + this.zBox = new QuadWidget.NumberEditBox(Minecraft.getInstance().font, i + ((k-3) / 3)*2 + 2, j, (k-4) / 3, l , Component.literal(vector.z +""), vector.z, d -> value.set(new Vector3f(vector.x, vector.y, d))); + } + + @Override + public void render(GuiGraphics guiGraphics, int i, int j, float f) { + this.xBox.render(guiGraphics, i, j, f); + this.yBox.render(guiGraphics, i, j, f); + this.zBox.render(guiGraphics, i, j, f); + } + + @Override + protected void renderWidget(GuiGraphics guiGraphics, int i, int j, float f) { + this.xBox.renderWidget(guiGraphics, i, j, f); + this.yBox.renderWidget(guiGraphics, i, j, f); + this.zBox.renderWidget(guiGraphics, i, j, f); + } + + @Override + public void renderTexture(GuiGraphics guiGraphics, ResourceLocation resourceLocation, int i, int j, int k, int l, int m, int n, int o, int p, int q) { + this.xBox.renderTexture(guiGraphics, resourceLocation, i, j, k, l, m, n, o, p, q); + this.yBox.renderTexture(guiGraphics, resourceLocation, i, j, k, l, m, n, o, p, q); + this.zBox.renderTexture(guiGraphics, resourceLocation, i, j, k, l, m, n, o, p, q); + } + + @Override + public void setX(int i) { + super.setX(i); + this.xBox.setX(i); + this.yBox.setX(i + (width-3)/3 + 1); + this.zBox.setX(i + ((width-3)/3)*2 + 2); + } + + @Override + public void setY(int i) { + super.setY(i); + this.xBox.setY(i); + this.yBox.setY(i); + this.zBox.setY(i); + } + + @Override + public void setFocused(boolean bl) { + super.setFocused(bl); + this.xBox.setFocused(this.xBox.isHovered()); + this.yBox.setFocused(this.yBox.isHovered()); + this.zBox.setFocused(this.zBox.isHovered()); + } + + @Override + public boolean mouseClicked(double d, double e, int i) { + if (xBox.isMouseOver(d, e)) { + this.xBox.setFocused(true); + return this.xBox.mouseClicked(d,e,i); + } + if (yBox.isMouseOver(d, e)) { + this.yBox.setFocused(true); + return this.yBox.mouseClicked(d,e,i); + } + if (zBox.isMouseOver(d, e)) { + this.zBox.setFocused(true); + return this.zBox.mouseClicked(d,e,i); + } + return super.mouseClicked(d, e, i); + } + + @Override + public boolean keyPressed(int i, int j, int k) { + if (this.xBox.isFocused()) { + return this.xBox.keyPressed(i, j, k); + } + if (this.yBox.isFocused()) { + return this.yBox.keyPressed(i, j, k); + } + if (this.zBox.isFocused()) { + return this.zBox.keyPressed(i, j, k); + } + return super.keyPressed(i, j, k); + } + + @Override + public boolean charTyped(char c, int i) { + if (this.xBox.isFocused()) { + return this.xBox.charTyped(c, i); + } + if (this.yBox.isFocused()) { + return this.yBox.charTyped(c, i); + } + if (this.zBox.isFocused()) { + return this.zBox.charTyped(c, i); + } + return super.charTyped(c, i); + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) { + + } +} diff --git a/common/src/main/java/org/vivecraft/server/config/ConfigBuilder.java b/common/src/main/java/org/vivecraft/common/ConfigBuilder.java similarity index 53% rename from common/src/main/java/org/vivecraft/server/config/ConfigBuilder.java rename to common/src/main/java/org/vivecraft/common/ConfigBuilder.java index d66b0a343..1f4185cdc 100644 --- a/common/src/main/java/org/vivecraft/server/config/ConfigBuilder.java +++ b/common/src/main/java/org/vivecraft/common/ConfigBuilder.java @@ -1,11 +1,17 @@ -package org.vivecraft.server.config; +package org.vivecraft.common; import com.electronwill.nightconfig.core.CommentedConfig; import com.electronwill.nightconfig.core.ConfigSpec; +import com.electronwill.nightconfig.core.EnumGetMethod; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.util.Mth; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.vivecraft.server.config.WidgetBuilder; +import java.lang.reflect.Array; import java.util.*; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -65,6 +71,24 @@ private void addDefaultValueComment(List path, double defaultValue, doub + new Formatter(Locale.US).format("default: %.2f, min: %.2f, max: %.2f", defaultValue, min, max)); } + private > void addDefaultValueComment(List path, T defaultValue) { + String oldComment = config.getComment(path); + config.setComment(path, (oldComment == null ? "" : oldComment + "\n ") + + new Formatter(Locale.US).format("default: %s", defaultValue.name())); + } + + private void addDefaultValueComment(List path, Quaternionf defaultValue) { + String oldComment = config.getComment(path); + config.setComment(path, (oldComment == null ? "" : oldComment + "\n ") + + "x: %.2f, y %.2f, z: %.2f, w: %.2f".formatted(defaultValue.x, defaultValue.y, defaultValue.z, defaultValue.w)); + } + + private void addDefaultValueComment(List path, Vector3f defaultValue) { + String oldComment = config.getComment(path); + config.setComment(path, (oldComment == null ? "" : oldComment + "\n ") + + "x: %.2f, y: %.2f, z: %.2f".formatted(defaultValue.x, defaultValue.y, defaultValue.z)); + } + /** * corrects the attached config, with the built spec * @@ -174,6 +198,72 @@ public StringValue define(String defaultValue) { return value; } + public > EnumValue define(T defaultValue) { + List path = stack.stream().toList(); + spec.defineEnum(path, defaultValue, EnumGetMethod.NAME); + stack.removeLast(); + addDefaultValueComment(path, defaultValue); + + EnumValue value = new EnumValue<>(config, path, defaultValue); + configValues.add(value); + return value; + } + + public QuatValue define(Quaternionf defaultValue) { + List path = stack.stream().toList(); + stack.add("x"); + spec.define(stack.stream().toList(), (double) defaultValue.x); + stack.removeLast(); + stack.add("y"); + spec.define(stack.stream().toList(), (double) defaultValue.y); + stack.removeLast(); + stack.add("z"); + spec.define(stack.stream().toList(), (double) defaultValue.z); + stack.removeLast(); + stack.add("w"); + spec.define(stack.stream().toList(), (double) defaultValue.w); + stack.removeLast(); + stack.removeLast(); + + addDefaultValueComment(path, defaultValue); + QuatValue value = new QuatValue(config, path, defaultValue); + configValues.add(value); + return value; + } + + public VectorValue define(Vector3f defaultValue) { + List path = stack.stream().toList(); + stack.add("x"); + spec.define(stack.stream().toList(), (double) defaultValue.x); + stack.removeLast(); + stack.add("y"); + spec.define(stack.stream().toList(), (double) defaultValue.y); + stack.removeLast(); + stack.add("z"); + spec.define(stack.stream().toList(), (double) defaultValue.z); + stack.removeLast(); + stack.removeLast(); + + addDefaultValueComment(path, defaultValue); + VectorValue value = new VectorValue(config, path, defaultValue); + configValues.add(value); + return value; + } + + public ArrayValue define(T[] defaultValue, Class clazz, Function fromString) { + List path = stack.stream().toList(); + for (int i = 0; i < defaultValue.length; i++) { + stack.add(i + ""); + spec.define(stack.stream().toList(), defaultValue[i]); + stack.removeLast(); + } + stack.removeLast(); + + ArrayValue value = new ArrayValue<>(config, path, defaultValue, clazz, fromString); + configValues.add(value); + return value; + } + /** * same as {@link #defineInRange defineInRange(T defaultValue, T min, T max)} but returns a {@link DoubleValue} */ @@ -206,11 +296,11 @@ public IntValue defineInRange(int defaultValue, int min, int max) { public static class ConfigValue { // the config, this setting is part of - private final CommentedConfig config; - private final List path; - private final T defaultValue; + protected final CommentedConfig config; + protected final List path; + protected final T defaultValue; // cache te value to minimize config lookups - private T cachedValue = null; + protected T cachedValue = null; public ConfigValue(CommentedConfig config, List path, T defaultValue) { this.config = config; @@ -237,6 +327,9 @@ public T reset() { } public boolean isDefault() { + if (get() instanceof Object[]) { + return Arrays.equals((Object[]) get(), (Object[]) defaultValue); + } return Objects.equals(get(), defaultValue); } @@ -361,4 +454,195 @@ public void fromNormalized(double value) { this.set(Math.round(newValue * 100.0) / 100.0); } } + + public static class EnumValue> extends ConfigValue { + + public EnumValue(CommentedConfig config, List path, T defaultValue) { + super(config, path, defaultValue); + } + + @Override + public T get() { + if (cachedValue == null) { + cachedValue = config.getEnumOrElse(path, defaultValue); + } + return cachedValue; + } + + @Override + public Supplier getWidget(int width, int height) { + return WidgetBuilder.getEnumWidget(this, width, height); + } + } + + public static class QuatValue extends ConfigValue { + + public QuatValue(CommentedConfig config, List path, Quaternionf defaultValue) { + super(config, path, defaultValue); + } + + @Override + public Quaternionf get() { + if (cachedValue == null) { + List path2 = new ArrayList<>(path); + path2.add("x"); + double x = config.get(path2); + path2.set(path.size(), "y"); + double y = config.get(path2); + path2.set(path.size(), "z"); + double z = config.get(path2); + path2.set(path.size(), "w"); + double w = config.get(path2); + cachedValue = new Quaternionf(x, y, z, w); + } + return new Quaternionf(cachedValue); + } + + @Override + public void set(Quaternionf newValue) { + cachedValue = newValue; + List path2 = new ArrayList<>(path); + path2.add("x"); + config.set(path2, (double) newValue.x); + path2.set(path.size(), "y"); + config.set(path2, (double) newValue.y); + path2.set(path.size(), "z"); + config.set(path2, (double) newValue.z); + path2.set(path.size(), "w"); + config.set(path2, (double) newValue.w); + } + + @Override + public Quaternionf reset() { + List path2 = new ArrayList<>(path); + path2.add("x"); + config.set(path2, (double) defaultValue.x); + path2.set(path.size(), "y"); + config.set(path2, (double) defaultValue.y); + path2.set(path.size(), "z"); + config.set(path2, (double) defaultValue.z); + path2.set(path.size(), "w"); + config.set(path2, (double) defaultValue.w); + cachedValue = defaultValue; + return defaultValue; + } + + @Override + public Supplier getWidget(int width, int height) { + return WidgetBuilder.getQuatWidget(this, width, height); + } + } + + public static class VectorValue extends ConfigValue { + + public VectorValue(CommentedConfig config, List path, Vector3f defaultValue) { + super(config, path, defaultValue); + } + + @Override + public Vector3f get() { + if (cachedValue == null) { + List path2 = new ArrayList<>(path); + path2.add("x"); + double x = config.get(path2); + path2.set(path.size(), "y"); + double y = config.get(path2); + path2.set(path.size(), "z"); + double z = config.get(path2); + cachedValue = new Vector3f((float) x, (float) y, (float) z); + } + return new Vector3f(cachedValue); + } + + @Override + public void set(Vector3f newValue) { + cachedValue = newValue; + List path2 = new ArrayList<>(path); + path2.add("x"); + config.set(path2, (double) newValue.x); + path2.set(path.size(), "y"); + config.set(path2, (double) newValue.y); + path2.set(path.size(), "z"); + config.set(path2, (double) newValue.z); + } + + @Override + public Vector3f reset() { + List path2 = new ArrayList<>(path); + path2.add("x"); + config.set(path2, (double) defaultValue.x); + path2.set(path.size(), "y"); + config.set(path2, (double) defaultValue.y); + path2.set(path.size(), "z"); + config.set(path2, (double) defaultValue.z); + cachedValue = defaultValue; + return defaultValue; + } + + @Override + public Supplier getWidget(int width, int height) { + return WidgetBuilder.getVectorWidget(this, width, height); + } + } + + public static class ArrayValue extends ConfigValue { + + private final Class clazz; + public final Function fromString; + + public ArrayValue(CommentedConfig config, List path, T[] defaultValue, Class clazz, Function fromString) { + super(config, path, defaultValue); + this.clazz = clazz; + this.fromString = fromString; + } + + @Override + public T[] get() { + if (cachedValue == null) { + List path2 = new ArrayList<>(path); + path2.add("0"); + T[] array = (T[]) Array.newInstance(clazz, defaultValue.length); + for (int i = 0; i < defaultValue.length; i++) { + path2.set(path.size(), i + ""); + T value = config.get(path2); + array[i] = value; + } + cachedValue = array; + } + return cachedValue; + } + + @Override + public void set(T[] newValue) { + cachedValue = newValue; + List path2 = new ArrayList<>(path); + path2.add("0"); + for (int i = 0; i < newValue.length; i++) { + path2.set(path.size(), i + ""); + config.set(path2, newValue[i]); + } + } + + @Override + public T[] reset() { + List path2 = new ArrayList<>(path); + path2.add("0"); + config.set(path2, defaultValue.length); + for (int i = 0; i < defaultValue.length; i++) { + path2.set(path.size(), i + ""); + config.set(path2, defaultValue[i]); + } + cachedValue = defaultValue; + return defaultValue; + } + + public T[] getDefault() { + return defaultValue; + } + + @Override + public Supplier getWidget(int width, int height) { + return WidgetBuilder.getArrayWidget(this, width, height); + } + } } diff --git a/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java b/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java index 5d301d599..21e7515b4 100644 --- a/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java @@ -19,7 +19,7 @@ import org.vivecraft.server.AimFixHandler; import org.vivecraft.server.ServerNetworking; import org.vivecraft.server.ServerVRPlayers; -import org.vivecraft.server.config.ServerConfig; +import org.vivecraft.server.ServerConfig; import static org.vivecraft.common.network.CommonNetworkHelper.PacketDiscriminators.CLIMBING; diff --git a/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java b/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java index 999712d83..655e94cbc 100644 --- a/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java @@ -32,9 +32,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.vivecraft.server.ServerConfig; import org.vivecraft.server.ServerVRPlayers; import org.vivecraft.server.ServerVivePlayer; -import org.vivecraft.server.config.ServerConfig; @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin extends Player { diff --git a/common/src/main/java/org/vivecraft/mixin/world/entity/ai/goal/SwellGoalMixin.java b/common/src/main/java/org/vivecraft/mixin/world/entity/ai/goal/SwellGoalMixin.java index a115c3f77..a04c7834a 100644 --- a/common/src/main/java/org/vivecraft/mixin/world/entity/ai/goal/SwellGoalMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/world/entity/ai/goal/SwellGoalMixin.java @@ -10,9 +10,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.vivecraft.server.ServerConfig; import org.vivecraft.server.ServerVRPlayers; import org.vivecraft.server.ServerVivePlayer; -import org.vivecraft.server.config.ServerConfig; @Mixin(SwellGoal.class) public class SwellGoalMixin { diff --git a/common/src/main/java/org/vivecraft/mixin/world/entity/projectile/AbstractArrowMixin.java b/common/src/main/java/org/vivecraft/mixin/world/entity/projectile/AbstractArrowMixin.java index e16333e60..ec716de41 100644 --- a/common/src/main/java/org/vivecraft/mixin/world/entity/projectile/AbstractArrowMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/world/entity/projectile/AbstractArrowMixin.java @@ -24,9 +24,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.vivecraft.common.utils.Utils; +import org.vivecraft.server.ServerConfig; import org.vivecraft.server.ServerVRPlayers; import org.vivecraft.server.ServerVivePlayer; -import org.vivecraft.server.config.ServerConfig; @Mixin(AbstractArrow.class) public abstract class AbstractArrowMixin extends Entity { diff --git a/common/src/main/java/org/vivecraft/server/AimFixHandler.java b/common/src/main/java/org/vivecraft/server/AimFixHandler.java index 4b470ec9f..ec17d7113 100644 --- a/common/src/main/java/org/vivecraft/server/AimFixHandler.java +++ b/common/src/main/java/org/vivecraft/server/AimFixHandler.java @@ -12,7 +12,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.phys.Vec3; -import org.vivecraft.server.config.ServerConfig; public class AimFixHandler extends ChannelInboundHandlerAdapter { private final Connection netManager; diff --git a/common/src/main/java/org/vivecraft/server/config/ServerConfig.java b/common/src/main/java/org/vivecraft/server/ServerConfig.java similarity index 99% rename from common/src/main/java/org/vivecraft/server/config/ServerConfig.java rename to common/src/main/java/org/vivecraft/server/ServerConfig.java index 8d4656599..3a4afb6cd 100644 --- a/common/src/main/java/org/vivecraft/server/config/ServerConfig.java +++ b/common/src/main/java/org/vivecraft/server/ServerConfig.java @@ -1,4 +1,4 @@ -package org.vivecraft.server.config; +package org.vivecraft.server; import com.electronwill.nightconfig.core.CommentedConfig; import com.electronwill.nightconfig.core.Config; @@ -7,6 +7,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import org.vivecraft.client.Xplat; +import org.vivecraft.common.ConfigBuilder; import java.util.Arrays; import java.util.List; diff --git a/common/src/main/java/org/vivecraft/server/ServerNetworking.java b/common/src/main/java/org/vivecraft/server/ServerNetworking.java index 31c894455..1be525f6b 100644 --- a/common/src/main/java/org/vivecraft/server/ServerNetworking.java +++ b/common/src/main/java/org/vivecraft/server/ServerNetworking.java @@ -17,7 +17,6 @@ import org.vivecraft.common.network.CommonNetworkHelper; import org.vivecraft.common.network.VrPlayerState; import org.vivecraft.mixin.server.ChunkMapAccessor; -import org.vivecraft.server.config.ServerConfig; import java.util.*; diff --git a/common/src/main/java/org/vivecraft/server/ServerUtil.java b/common/src/main/java/org/vivecraft/server/ServerUtil.java index 6a6548ff5..7a2fde35a 100644 --- a/common/src/main/java/org/vivecraft/server/ServerUtil.java +++ b/common/src/main/java/org/vivecraft/server/ServerUtil.java @@ -7,8 +7,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import org.vivecraft.client.utils.UpdateChecker; -import org.vivecraft.server.config.ConfigBuilder; -import org.vivecraft.server.config.ServerConfig; +import org.vivecraft.common.ConfigBuilder; import java.util.List; import java.util.concurrent.Executors; diff --git a/common/src/main/java/org/vivecraft/server/config/WidgetBuilder.java b/common/src/main/java/org/vivecraft/server/config/WidgetBuilder.java index 6b5ee9fcb..72b9c892e 100644 --- a/common/src/main/java/org/vivecraft/server/config/WidgetBuilder.java +++ b/common/src/main/java/org/vivecraft/server/config/WidgetBuilder.java @@ -3,7 +3,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.*; import net.minecraft.network.chat.Component; +import org.vivecraft.client.gui.settings.GuiArrayValueEditScreen; import org.vivecraft.client.gui.settings.GuiListValueEditScreen; +import org.vivecraft.client.gui.widgets.QuadWidget; +import org.vivecraft.client.gui.widgets.VectorWidget; +import org.vivecraft.common.ConfigBuilder; import java.util.function.Supplier; @@ -91,4 +95,35 @@ public static Supplier getEditListWidget(ConfigBuilder.ListV .tooltip(Tooltip.create(Component.literal(listValue.getComment()))) .build(); } + + public static > Supplier getEnumWidget(ConfigBuilder.EnumValue enumValue, int width, int height) { + return () -> CycleButton + .builder(newValue -> Component.literal(newValue.toString())) + .withInitialValue(enumValue.get()) + .withValues(enumValue.get().getDeclaringClass().getEnumConstants()) + .displayOnlyValue() + .withTooltip((bool) -> enumValue.getComment() != null ? Tooltip.create(Component.literal(enumValue.getComment())) : null) + .create(0, 0, width, height, Component.empty(), (button, newValue) -> enumValue.set(newValue)); + } + + public static Supplier getQuatWidget(ConfigBuilder.QuatValue quatValue, int width, int height) { + return () -> new QuadWidget(0,0, width, height, Component.literal(quatValue.get().toString()), quatValue); + } + + public static Supplier getVectorWidget(ConfigBuilder.VectorValue vectorValue, int width, int height) { + return () -> new VectorWidget(0,0, width, height, Component.literal(vectorValue.get().toString()), vectorValue); + } + + public static Supplier getArrayWidget(ConfigBuilder.ArrayValue arrayValue, int width, int height) { + return () -> Button + .builder( + Component.translatable("vivecraft.options.editarray"), + button -> Minecraft.getInstance() + .setScreen( + new GuiArrayValueEditScreen<>(Component.literal(arrayValue.getPath().substring(arrayValue.getPath().lastIndexOf("."))), Minecraft.getInstance().screen, arrayValue, arrayValue.fromString) + )) + .size(width, height) + .tooltip(Tooltip.create(Component.literal(arrayValue.getComment()))) + .build(); + } } diff --git a/fabric/build.gradle b/fabric/build.gradle index cee714949..012807175 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -49,6 +49,7 @@ dependencies { //mod menu modApi("com.terraformersmc:modmenu:7.2.2") + modRuntimeOnly("com.terraformersmc:modmenu:7.2.2") // for immersive portals compat modRuntimeOnly('com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:v3.3.1-mc1.20.1') { diff --git a/fabric/src/main/java/org/vivecraft/fabric/VivecraftMod.java b/fabric/src/main/java/org/vivecraft/fabric/VivecraftMod.java index 1ea3fe2ef..d2e1e9083 100644 --- a/fabric/src/main/java/org/vivecraft/fabric/VivecraftMod.java +++ b/fabric/src/main/java/org/vivecraft/fabric/VivecraftMod.java @@ -2,14 +2,16 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import org.vivecraft.client.ClientConfig; +import org.vivecraft.server.ServerConfig; import org.vivecraft.server.ServerUtil; -import org.vivecraft.server.config.ServerConfig; public class VivecraftMod implements ModInitializer { @Override public void onInitialize() { // init server config ServerConfig.init(null); + ClientConfig.init(null); // add server config commands CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> diff --git a/forge/build.gradle b/forge/build.gradle index f35f564e1..e8040a25e 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -47,7 +47,7 @@ dependencies { common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false } - modRuntimeOnly("maven.modrinth:rubidium:0.6.5") + modRuntimeOnly("maven.modrinth:rubidium:0.6.4") modRuntimeOnly("maven.modrinth:oculus:1.20-1.6.4") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.1") diff --git a/forge/src/main/java/org/vivecraft/forge/Vivecraft.java b/forge/src/main/java/org/vivecraft/forge/Vivecraft.java index c53e4f82b..4c40327f1 100644 --- a/forge/src/main/java/org/vivecraft/forge/Vivecraft.java +++ b/forge/src/main/java/org/vivecraft/forge/Vivecraft.java @@ -1,7 +1,8 @@ package org.vivecraft.forge; import net.minecraftforge.fml.common.Mod; -import org.vivecraft.server.config.ServerConfig; +import org.vivecraft.client.ClientConfig; +import org.vivecraft.server.ServerConfig; @Mod(Vivecraft.MODID) public class Vivecraft { @@ -10,5 +11,6 @@ public class Vivecraft { public Vivecraft() { // init server config ServerConfig.init(null); + ClientConfig.init(null); } }