Skip to content

Commit

Permalink
config DSL, fix ordering of subconfigs, fix log spam in prod, hopeful…
Browse files Browse the repository at this point in the history
…ly finally fix keybind issues, fix using UMatrixStack.Compat, window focus event, fix resizing of the oneconfig instance, fix HUD editor being incorrectly clipped
  • Loading branch information
nextdayy committed Feb 14, 2025
1 parent 285b846 commit 6b14be3
Show file tree
Hide file tree
Showing 13 changed files with 323 additions and 7 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name=OneConfig
mod_id=oneconfig
version_major=1
version_minor=0
version_patch=0-alpha.65
version_patch=0-alpha.67

polyfrost.defaults.loom=3

Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ kotlin = "2.0.20"
kotlinx-coroutines = "1.8.1"
kotlinx-atomicfu = "0.24.0"
fabric-language-kotlin = "1.12.2+kotlin.2.0.20"
polyui = "1.7.385"
polyui = "1.7.386"
annotations = "24.1.0"
hypixel-modapi = "1.0"
hypixel-data = "0.1.2" # Dep of hypixel-modapi
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
package org.polyfrost.oneconfig.api.config.v1.dsl

import org.jetbrains.annotations.ApiStatus
import org.polyfrost.oneconfig.api.config.v1.Properties
import org.polyfrost.oneconfig.api.config.v1.Tree
import org.polyfrost.oneconfig.api.config.v1.Visualizer
import org.polyfrost.polyui.color.PolyColor
import org.polyfrost.polyui.input.KeyBinder

/**
* Experimental DSL for creating config trees.
*
* **Note that for Java compatability,** unlike most Kotlin DSLs, this on requires you to add `.apply { ... }`
* instead of just `{ ... }` to the end of any the functions in order to configure them.
*/
@ApiStatus.Experimental
class ConfigDSL(id: String? = null, title: String? = null, description: String? = null) {
val tree = Tree(id, title, description, null)


fun subconfig(id: String? = null, title: String? = null, description: String? = null): ConfigDSL {
val out = ConfigDSL(id, title, description)
tree.put(out.tree)
return out
}

fun accordion(id: String? = null, title: String? = null, description: String? = null): ConfigDSL {
val out = ConfigDSL(id, title, description)
tree.put(out.tree)
return out
}

fun switch(default: Boolean): Prop<Boolean> {
val prop = Prop(default, Boolean::class.java)
prop["visualizer"] = Visualizer.SwitchVisualizer::class.java
tree.put(prop.property)
return prop
}

fun checkbox(default: Boolean): Prop<Boolean> {
val prop = Prop(default, Boolean::class.java)
prop["visualizer"] = Visualizer.CheckboxVisualizer::class.java
tree.put(prop.property)
return prop
}

fun button(function: Runnable): RunnableProp {
val prop = RunnableProp(function)
prop["visualizer"] = Visualizer.ButtonVisualizer::class.java
tree.put(prop.property)
return prop
}

fun color(default: PolyColor): ColorProp {
val prop = ColorProp(default)
prop["visualizer"] = Visualizer.ColorVisualizer::class.java
tree.put(prop.property)
return prop
}

fun text(default: String): TextProp {
val prop = TextProp(default)
prop["visualizer"] = Visualizer.TextVisualizer::class.java
tree.put(prop.property)
return prop
}

fun slider(default: Float): FloatProp {
val prop = FloatProp(default)
prop["visualizer"] = Visualizer.SliderVisualizer::class.java
tree.put(prop.property)
return prop
}

fun slider(default: Int): IntProp {
val prop = IntProp(default)
prop["visualizer"] = Visualizer.SliderVisualizer::class.java
tree.put(prop.property)
return prop
}

fun number(default: Float): FloatProp {
val prop = FloatProp(default)
prop["visualizer"] = Visualizer.NumberVisualizer::class.java
tree.put(prop.property)
return prop
}

fun number(default: Int): IntProp {
val prop = IntProp(default)
prop["visualizer"] = Visualizer.NumberVisualizer::class.java
tree.put(prop.property)
return prop
}

fun keybind(default: KeyBinder.Bind): Prop<KeyBinder.Bind> {
val prop = Prop(default, KeyBinder.Bind::class.java)
prop["visualizer"] = Visualizer.KeybindVisualizer::class.java
tree.put(prop.property)
return prop
}

fun dropdown(defaultIndex: Int, vararg options: String): Prop<Int> {
val prop = Prop(defaultIndex, Int::class.java)
prop["visualizer"] = Visualizer.DropdownVisualizer::class.java
prop["options"] = options
tree.put(prop.property)
return prop
}

inline fun <reified T : Enum<*>> dropdown(default: T): Prop<T> {
val prop = Prop(default, T::class.java)
prop["visualizer"] = Visualizer.DropdownVisualizer::class.java
tree.put(prop.property)
return prop
}

fun radiobutton(defaultIndex: Int, vararg options: String): Prop<Int> {
val prop = Prop(defaultIndex, Int::class.java)
prop["visualizer"] = Visualizer.RadioVisualizer::class.java
prop["options"] = options
tree.put(prop.property)
return prop
}

inline fun <reified T : Enum<*>> radiobutton(default: T): Prop<T> {
val prop = Prop(default, T::class.java)
prop["visualizer"] = Visualizer.RadioVisualizer::class.java
tree.put(prop.property)
return prop
}



class IntProp(default: Int) : Prop<Int>(default, Int::class.java) {
var min: Int
get() = (this["min"] as Float).toInt()
set(value) { this["min"] = value.toFloat() }

var max: Int
get() = (this["max"] as Float).toInt()
set(value) { this["max"] = value.toFloat() }

var unit: String?
get() = this["unit"] as String?
set(value) { this["unit"] = value }
}

class FloatProp(default: Float) : Prop<Float>(default, Float::class.java) {
var min: Float
get() = this["min"] as Float
set(value) { this["min"] = value }

var max: Float
get() = this["max"] as Float
set(value) { this["max"] = value }

var unit: String?
get() = this["unit"] as String?
set(value) { this["unit"] = value }
}

class RunnableProp(action: Runnable) : Prop<Runnable>(action, Runnable::class.java) {
var action: Runnable?
get() = value
set(value) { this.value = value }

var text: String?
get() = this["text"] as String?
set(value) { this["text"] = value }
}

class ColorProp(default: PolyColor) : Prop<PolyColor>(default, PolyColor::class.java) {
var alpha: Boolean
get() = this["alpha"] as Boolean
set(value) { this["alpha"] = value }
}

class TextProp(default: String) : Prop<String>(default, String::class.java) {
var placeholder: String?
get() = this["placeholder"] as String?
set(value) { this["placeholder"] = value }
}


open class Prop<T : Any>(default: T?, typeOfT: Class<T>) {
val property = Properties.simple(null, null, null, default, typeOfT)

var value
get() = property.get()
set(value) { property.set(value) }

var id: String?
get() = property.id
set(value) { property.id = value }

var title: String?
get() = property.title
set(value) { property.title = value }

var description: String?
get() = property.description
set(value) { property.description = value }

operator fun set(key: String, value: Any?) {
property.addMetadata(key, value)
}

operator fun get(key: String): Any? = property.getMetadata(key)
}

@DslMarker
private annotation class ConfigDSLMarker

companion object {
@ConfigDSLMarker
@JvmStatic
inline fun config(id: String? = null, title: String? = null, description: String? = null, block: ConfigDSL.() -> Unit) {
ConfigDSL(id, title, description).apply(block)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ open class ConfigVisualizer {
initialPage: String = "General",
): Drawable {
val now = System.nanoTime()
val options = HashMap<String, HashMap<String, ArrayList<Drawable>>>(4)
val options = LinkedHashMap<String, HashMap<String, ArrayList<Drawable>>>(4)

// asm: step 1: sort the tree into a map of:
// categories
Expand Down Expand Up @@ -171,7 +171,7 @@ open class ConfigVisualizer {
val category = node.getMetadata<String>("category")?.strv() ?: "General"
val subcategory = node.getMetadata<String>("subcategory")?.strv() ?: "General"

val list = options.getOrPut(category) { HashMap(4) }.getOrPut(subcategory) { ArrayList(8) }
val list = options.getOrPut(category) { LinkedHashMap(4) }.getOrPut(subcategory) { ArrayList(8) }
if (node is Property<*>) {
val vis = node.getVisualizer() ?: return
list.add(wrap(vis.visualize(node), node.title, node.description, icon).addHideHandler(node).linkTo(node))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* This file is part of OneConfig.
* OneConfig - Next Generation Config Library for Minecraft: Java Edition
* Copyright (C) 2021~2024 Polyfrost.
* <https://polyfrost.org> <https://github.com/Polyfrost/>
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* OneConfig is licensed under the terms of version 3 of the GNU Lesser
* General Public License as published by the Free Software Foundation, AND
* under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
* either version 1.0 of the Additional Terms, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License. If not, see <https://www.gnu.org/licenses/>. You should
* have also received a copy of the Additional Terms Applicable
* to OneConfig, as published by Polyfrost. If not, see
* <https://polyfrost.org/legal/oneconfig/additional-terms>
*/

package org.polyfrost.oneconfig.api.event.v1.events;

// dispatching handled in OneConfig.java for legacy as needs version specific handling heheheheeeeee

/**
* Events relating to window focus.
*/
public interface WindowFocusEvent extends Event {
class Gained implements WindowFocusEvent {
public static final Gained INSTANCE = new Gained();

private Gained() {
}
}

class Lost implements WindowFocusEvent {
public static final Lost INSTANCE = new Lost();

private Lost() {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.polyfrost.oneconfig.api.event.v1.eventHandler
import org.polyfrost.oneconfig.api.event.v1.events.KeyInputEvent
import org.polyfrost.oneconfig.api.event.v1.events.ScreenOpenEvent
import org.polyfrost.oneconfig.api.event.v1.events.TickEvent
import org.polyfrost.oneconfig.api.event.v1.events.WindowFocusEvent
import org.polyfrost.polyui.Settings
import org.polyfrost.polyui.input.InputManager
import org.polyfrost.polyui.input.KeyBinder
Expand Down Expand Up @@ -67,6 +68,9 @@ object KeybindManager {
eventHandler { (screen): ScreenOpenEvent ->
if (screen == null) keyBinder.release()
}
eventHandler { _: WindowFocusEvent.Lost ->
keyBinder.release()
}

val m = Int2IntMap(8)
m[UKeyboard.KEY_LSHIFT] = KeyModifiers.LSHIFT.value.toInt()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.polyfrost.oneconfig.internal.mixin.events;

import net.minecraft.client.Minecraft;
import org.polyfrost.oneconfig.api.event.v1.EventManager;
import org.polyfrost.oneconfig.api.event.v1.events.WindowFocusEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;


@Mixin(Minecraft.class)
public class Mixin_ModernWindowFocusEvent {
@Inject(method = "setGameFocused", at = @At("HEAD"))
private void onGameFocused(boolean focused, CallbackInfo ci) {
if (focused) EventManager.INSTANCE.post(WindowFocusEvent.Gained.INSTANCE);
else EventManager.INSTANCE.post(WindowFocusEvent.Lost.INSTANCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.polyfrost.oneconfig.api.event.v1.EventManager;
import org.polyfrost.oneconfig.api.event.v1.events.HypixelLocationEvent;
import org.polyfrost.oneconfig.api.event.v1.events.ReceivePacketEvent;
import org.polyfrost.oneconfig.api.platform.v1.Platform;

/**
* Heavily adapted from Hypixel/ForgeModAPI under the MIT licence.
Expand All @@ -60,7 +61,7 @@ private void registerHypixelApi() {
HypixelModAPI.getInstance().setPacketSender((packet) -> {
NetHandlerPlayClient net = Minecraft.getMinecraft().getNetHandler();
if (net == null) {
LOGGER.warn("dropping packet {} because no net handler is available, retrying in 1s", packet);
if (Platform.loader().isDevelopment()) LOGGER.warn("dropping packet {} because no net handler is available, retrying in 1s", packet);
EventDelay.tick(20, () -> HypixelModAPI.getInstance().sendPacket(packet));
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public PolyUIScreen(@NotNull PolyUI polyUI, float designedWidth, float designedH
this.blurs = blurs;
this.pauses = pauses;
this.close = onClose;
}

@Override
public void initScreen(int width, int height) {
adjustResolution(Platform.screen().windowWidth(), Platform.screen().windowHeight(), false);
}

Expand Down
Loading

0 comments on commit 6b14be3

Please sign in to comment.