Compare commits
4 Commits
ba6153fa41
...
8498a77735
Author | SHA1 | Date | |
---|---|---|---|
8498a77735 | |||
0dd5907a29 | |||
c25790902c | |||
f51bde3d6e |
16
README.md
16
README.md
@ -49,12 +49,26 @@ As a challenge I'm trying to make it as user-friendly as possible.
|
||||
- Toggleable
|
||||
- Keybinding for /camera
|
||||
|
||||
# Currently working on
|
||||
|
||||
## Client Side
|
||||
|
||||
- [x] Render block entities from a longer range
|
||||
- [x] Toggleable via GUI
|
||||
- [x] Configurable value
|
||||
- [x] In GUI
|
||||
- [x] Rework Mod Menu integration to be more flexible
|
||||
- The following types are accepted:
|
||||
- String
|
||||
- Boolean
|
||||
- Float
|
||||
- Integer
|
||||
|
||||
# To-do
|
||||
|
||||
## General
|
||||
- Rework config system
|
||||
- Store server settings in world folder for better singleplayer use
|
||||
- Rework Mod Menu integration to be more flexible
|
||||
|
||||
## Server Side
|
||||
- Telekinesis
|
||||
|
@ -9,7 +9,7 @@ yarn_mappings=1.21.5+build.1
|
||||
loader_version=0.16.10
|
||||
|
||||
# Mod Properties
|
||||
mod_version=1.4.0
|
||||
mod_version=1.4.1
|
||||
maven_group=wtf.hak.survivalfabric
|
||||
archives_base_name=survivalfabric
|
||||
|
||||
|
@ -11,4 +11,6 @@ public class ClientConfig {
|
||||
public boolean renderSnowFog = false;
|
||||
public boolean removeDarknessEffect = true;
|
||||
public boolean lockTeleportHeadMovement = true;
|
||||
public boolean manipulateBlockEntityDistance = true;
|
||||
public int blockEntityRange = 512;
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package wtf.hak.survivalfabric.mixin.client;
|
||||
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import wtf.hak.survivalfabric.config.client.ClientConfigManager;
|
||||
|
||||
@Mixin(BlockEntityRenderer.class)
|
||||
public interface BlockEntityRendererMixin<T extends BlockEntity> {
|
||||
|
||||
@Inject(method = "getRenderDistance", at = @At("HEAD"), cancellable = true)
|
||||
private void getRenderDistance(CallbackInfoReturnable<Integer> cir) {
|
||||
if(ClientConfigManager.getConfig().manipulateBlockEntityDistance)
|
||||
cir.setReturnValue(ClientConfigManager.getConfig().blockEntityRange);
|
||||
}
|
||||
}
|
@ -3,15 +3,29 @@ package wtf.hak.survivalfabric.modmenu;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import wtf.hak.survivalfabric.config.client.ClientConfig;
|
||||
import wtf.hak.survivalfabric.config.client.ClientConfigManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigScreen extends Screen {
|
||||
|
||||
private static final int OPTION_HEIGHT = 25;
|
||||
private static final int SCROLL_BAR_WIDTH = 6;
|
||||
private static final int TOP_PADDING = 40;
|
||||
private static final int BOTTOM_PADDING = 35;
|
||||
private static final int SIDE_PADDING = 20;
|
||||
private final Screen parent;
|
||||
private final List<ConfigOption<?>> options = new ArrayList<>();
|
||||
private TextFieldWidget activeTextField = null;
|
||||
private float scrollPosition = 0.0F;
|
||||
private boolean scrolling = false;
|
||||
private int contentHeight = 0;
|
||||
|
||||
public ConfigScreen(Screen parent) {
|
||||
super(Text.literal("Survival Fabric - Client Config"));
|
||||
@ -20,55 +34,272 @@ public class ConfigScreen extends Screen {
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
int buttonWidth = 200;
|
||||
int buttonHeight = 20;
|
||||
int spacing = 5;
|
||||
int startY = 40;
|
||||
int i = 0;
|
||||
options.clear();
|
||||
|
||||
int listWidth = this.width - (SIDE_PADDING * 2);
|
||||
int listHeight = this.height - TOP_PADDING - BOTTOM_PADDING;
|
||||
int listLeft = SIDE_PADDING;
|
||||
int listTop = TOP_PADDING;
|
||||
|
||||
int index = 0;
|
||||
for (Field field : ClientConfig.class.getFields()) {
|
||||
if (field.getType() == boolean.class) {
|
||||
int y = startY + i * (buttonHeight + spacing);
|
||||
try {
|
||||
try {
|
||||
Class<?> type = field.getType();
|
||||
String name = formatFieldName(field.getName());
|
||||
|
||||
ConfigOption<?> option = null;
|
||||
if (type == boolean.class) {
|
||||
boolean value = field.getBoolean(ClientConfigManager.getConfig());
|
||||
String label = formatFieldName(field.getName()) + ": " + (value ? "ON" : "OFF");
|
||||
|
||||
ButtonWidget button = ButtonWidget.builder(
|
||||
Text.literal(label),
|
||||
b -> {
|
||||
try {
|
||||
boolean current = field.getBoolean(ClientConfigManager.getConfig());
|
||||
field.setBoolean(ClientConfigManager.getConfig(), !current);
|
||||
b.setMessage(Text.literal(formatFieldName(field.getName()) + ": " + (!current ? "ON" : "OFF")));
|
||||
ClientConfigManager.save(); // Save if needed
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
).dimensions(this.width / 2 - buttonWidth / 2, y, buttonWidth, buttonHeight).build();
|
||||
|
||||
this.addDrawableChild(button);
|
||||
i++;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
option = new BooleanConfigOption(
|
||||
name,
|
||||
field,
|
||||
value,
|
||||
listLeft,
|
||||
listTop + (index * OPTION_HEIGHT) - (int) scrollPosition,
|
||||
listWidth
|
||||
);
|
||||
} else if (type == int.class) {
|
||||
int value = field.getInt(ClientConfigManager.getConfig());
|
||||
option = new IntegerConfigOption(
|
||||
name,
|
||||
field,
|
||||
value,
|
||||
listLeft,
|
||||
listTop + (index * OPTION_HEIGHT) - (int) scrollPosition,
|
||||
listWidth
|
||||
);
|
||||
} else if (type == float.class) {
|
||||
float value = field.getFloat(ClientConfigManager.getConfig());
|
||||
option = new FloatConfigOption(
|
||||
name,
|
||||
field,
|
||||
value,
|
||||
listLeft,
|
||||
listTop + (index * OPTION_HEIGHT) - (int) scrollPosition,
|
||||
listWidth
|
||||
);
|
||||
} else if (type == String.class) {
|
||||
String value = (String) field.get(ClientConfigManager.getConfig());
|
||||
option = new StringConfigOption(
|
||||
name,
|
||||
field,
|
||||
value,
|
||||
listLeft,
|
||||
listTop + (index * OPTION_HEIGHT) - (int) scrollPosition,
|
||||
listWidth
|
||||
);
|
||||
}
|
||||
|
||||
if (option != null) {
|
||||
options.add(option);
|
||||
index++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for (ConfigOption<?> option : options) {
|
||||
if (option instanceof NumericConfigOption) {
|
||||
((NumericConfigOption<?>) option).createTextField(this.client);
|
||||
}
|
||||
}
|
||||
|
||||
contentHeight = options.size() * OPTION_HEIGHT;
|
||||
|
||||
this.addDrawableChild(ButtonWidget.builder(
|
||||
Text.translatable("gui.done"),
|
||||
button -> this.client.setScreen(parent)
|
||||
).dimensions(this.width / 2 - 75, startY + i * (buttonHeight + spacing) + 10, 150, 20).build());
|
||||
).dimensions(this.width / 2 - 100, this.height - 27, 200, 20).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
context.fill(0, 0, this.width, this.height, 0xC0101010);
|
||||
this.renderBackground(context, mouseX, mouseY, delta);
|
||||
|
||||
int titleX = (this.width / 2) - (this.textRenderer.getWidth(this.title) / 2);
|
||||
context.drawTextWithShadow(this.textRenderer, this.title, titleX, 20, 0xFFFFFF);
|
||||
context.drawText(this.textRenderer, this.title, titleX, 15, 0xFFFFFF, true);
|
||||
|
||||
super.render(context, mouseX, mouseY, delta);
|
||||
int listWidth = this.width - (SIDE_PADDING * 2);
|
||||
int listHeight = this.height - TOP_PADDING - BOTTOM_PADDING;
|
||||
int listLeft = SIDE_PADDING;
|
||||
int listTop = TOP_PADDING;
|
||||
|
||||
context.drawBorder(listLeft, listTop, listLeft + listWidth, listTop + listHeight, 0x00000000);
|
||||
|
||||
context.enableScissor(
|
||||
listLeft,
|
||||
listTop,
|
||||
listLeft + listWidth,
|
||||
listTop + listHeight
|
||||
);
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
ConfigOption<?> option = options.get(i);
|
||||
option.y = listTop + (i * OPTION_HEIGHT) - (int) scrollPosition;
|
||||
|
||||
if (option instanceof NumericConfigOption) {
|
||||
((NumericConfigOption<?>) option).updateTextFieldPosition();
|
||||
}
|
||||
|
||||
if (option.y < listTop + listHeight && option.y + OPTION_HEIGHT > listTop) {
|
||||
option.render(context, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
|
||||
context.disableScissor();
|
||||
|
||||
if (contentHeight > listHeight) {
|
||||
int scrollBarHeight = Math.max(20, (int) ((float) listHeight / (float) contentHeight * listHeight));
|
||||
int scrollBarY = listTop + (int) ((scrollPosition / (contentHeight - listHeight)) * (listHeight - scrollBarHeight));
|
||||
|
||||
context.fill(
|
||||
listLeft + listWidth + 2,
|
||||
listTop,
|
||||
listLeft + listWidth + 2 + SCROLL_BAR_WIDTH,
|
||||
listTop + listHeight,
|
||||
0xFF404040
|
||||
);
|
||||
|
||||
context.fill(
|
||||
listLeft + listWidth + 2,
|
||||
scrollBarY,
|
||||
listLeft + listWidth + 2 + SCROLL_BAR_WIDTH,
|
||||
scrollBarY + scrollBarHeight,
|
||||
scrolling ? 0xFFAAAAAA : 0xFF808080
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
int listWidth = this.width - (SIDE_PADDING * 2);
|
||||
int listHeight = this.height - TOP_PADDING - BOTTOM_PADDING;
|
||||
int listLeft = SIDE_PADDING;
|
||||
int listTop = TOP_PADDING;
|
||||
|
||||
boolean handledByTextField = false;
|
||||
|
||||
activeTextField = null;
|
||||
|
||||
if (mouseX >= listLeft &&
|
||||
mouseX <= listLeft + listWidth &&
|
||||
mouseY >= listTop &&
|
||||
mouseY <= listTop + listHeight) {
|
||||
|
||||
for (ConfigOption<?> option : options) {
|
||||
if (option instanceof NumericConfigOption<?> numOption &&
|
||||
option.y >= listTop &&
|
||||
option.y + OPTION_HEIGHT <= listTop + listHeight) {
|
||||
|
||||
TextFieldWidget textField = numOption.getTextField();
|
||||
|
||||
if (textField.isMouseOver(mouseX, mouseY)) {
|
||||
textField.setFocused(true);
|
||||
activeTextField = textField;
|
||||
handledByTextField = true;
|
||||
|
||||
for (ConfigOption<?> otherOption : options) {
|
||||
if (otherOption instanceof NumericConfigOption && otherOption != option) {
|
||||
((NumericConfigOption<?>) otherOption).getTextField().setFocused(false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
textField.setFocused(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contentHeight > listHeight &&
|
||||
mouseX >= listLeft + listWidth + 2 &&
|
||||
mouseX <= listLeft + listWidth + 2 + SCROLL_BAR_WIDTH &&
|
||||
mouseY >= listTop &&
|
||||
mouseY <= listTop + listHeight) {
|
||||
|
||||
scrolling = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if clicked on an option
|
||||
if (mouseX >= listLeft &&
|
||||
mouseX <= listLeft + listWidth &&
|
||||
mouseY >= listTop &&
|
||||
mouseY <= listTop + listHeight) {
|
||||
|
||||
for (ConfigOption<?> option : options) {
|
||||
if (option.isMouseOver(mouseX, mouseY) && option.y >= listTop && option.y + OPTION_HEIGHT <= listTop + listHeight) {
|
||||
option.onClick(mouseX, mouseY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
if (activeTextField != null && activeTextField.isFocused()) {
|
||||
return activeTextField.keyPressed(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
return super.keyPressed(keyCode, scanCode, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char chr, int modifiers) {
|
||||
if (activeTextField != null && activeTextField.isFocused()) {
|
||||
return activeTextField.charTyped(chr, modifiers);
|
||||
}
|
||||
|
||||
return super.charTyped(chr, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
scrolling = false;
|
||||
return super.mouseReleased(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||
int listHeight = this.height - TOP_PADDING - BOTTOM_PADDING;
|
||||
int listTop = TOP_PADDING;
|
||||
|
||||
if (scrolling && contentHeight > listHeight) {
|
||||
float scrollAmount = (float) deltaY / (listHeight - Math.max(20, (int) ((float) listHeight / (float) contentHeight * listHeight)));
|
||||
float maxScroll = contentHeight - listHeight;
|
||||
|
||||
scrollPosition = MathHelper.clamp(scrollPosition + scrollAmount * maxScroll, 0.0F, maxScroll);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
|
||||
int listWidth = this.width - (SIDE_PADDING * 2);
|
||||
int listHeight = this.height - TOP_PADDING - BOTTOM_PADDING;
|
||||
int listLeft = SIDE_PADDING;
|
||||
int listTop = TOP_PADDING;
|
||||
|
||||
if (mouseX >= listLeft &&
|
||||
mouseX <= listLeft + listWidth &&
|
||||
mouseY >= listTop &&
|
||||
mouseY <= listTop + listHeight &&
|
||||
contentHeight > listHeight) {
|
||||
|
||||
float maxScroll = contentHeight - listHeight;
|
||||
scrollPosition = MathHelper.clamp(scrollPosition - (float) verticalAmount * 10, 0.0F, maxScroll);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
|
||||
}
|
||||
|
||||
private String formatFieldName(String rawName) {
|
||||
@ -84,4 +315,285 @@ public class ConfigScreen extends Screen {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Base class for all config options
|
||||
*/
|
||||
private abstract class ConfigOption<T> {
|
||||
protected final String name;
|
||||
protected final Field field;
|
||||
protected final int width;
|
||||
protected T value;
|
||||
protected int x;
|
||||
protected int y;
|
||||
|
||||
public ConfigOption(String name, Field field, T initialValue, int x, int y, int width) {
|
||||
this.name = name;
|
||||
this.field = field;
|
||||
this.value = initialValue;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public abstract void render(DrawContext context, int mouseX, int mouseY, float delta);
|
||||
|
||||
public abstract void onClick(double mouseX, double mouseY);
|
||||
|
||||
public boolean isMouseOver(double mouseX, double mouseY) {
|
||||
return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + OPTION_HEIGHT;
|
||||
}
|
||||
|
||||
protected abstract void saveValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for boolean config options
|
||||
*/
|
||||
private class BooleanConfigOption extends ConfigOption<Boolean> {
|
||||
private static final int BUTTON_WIDTH = 40;
|
||||
private static final int BUTTON_HEIGHT = 20;
|
||||
|
||||
public BooleanConfigOption(String name, Field field, Boolean initialValue, int x, int y, int width) {
|
||||
super(name, field, initialValue, x, y, width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
context.drawText(textRenderer, name, x + 5, y + (OPTION_HEIGHT - 8) / 2, 0xFFFFFF, true);
|
||||
|
||||
int buttonX = x + width - BUTTON_WIDTH - 5;
|
||||
int buttonY = y + (OPTION_HEIGHT - BUTTON_HEIGHT) / 2;
|
||||
|
||||
boolean hovered = isButtonHovered(mouseX, mouseY);
|
||||
int buttonColor = hovered ? 0xFF404040 : 0xFF303030;
|
||||
int buttonBorder = hovered ? 0xFFCCCCCC : 0xFF808080;
|
||||
|
||||
context.fill(buttonX, buttonY, buttonX + BUTTON_WIDTH, buttonY + BUTTON_HEIGHT, buttonBorder);
|
||||
context.fill(buttonX + 1, buttonY + 1, buttonX + BUTTON_WIDTH - 1, buttonY + BUTTON_HEIGHT - 1, buttonColor);
|
||||
|
||||
String buttonText = value ? "true" : "false";
|
||||
int textColor = value ? 0x00be00 : 0xbe0000;
|
||||
int textWidth = textRenderer.getWidth(buttonText);
|
||||
context.drawText(
|
||||
textRenderer,
|
||||
buttonText,
|
||||
buttonX + (BUTTON_WIDTH - textWidth) / 2,
|
||||
buttonY + (BUTTON_HEIGHT - 8) / 2,
|
||||
textColor,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isButtonHovered(double mouseX, double mouseY) {
|
||||
int buttonX = x + width - BUTTON_WIDTH - 5;
|
||||
int buttonY = y + (OPTION_HEIGHT - BUTTON_HEIGHT) / 2;
|
||||
return mouseX >= buttonX && mouseX <= buttonX + BUTTON_WIDTH &&
|
||||
mouseY >= buttonY && mouseY <= buttonY + BUTTON_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(double mouseX, double mouseY) {
|
||||
if (isButtonHovered(mouseX, mouseY)) {
|
||||
value = !value;
|
||||
saveValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveValue() {
|
||||
try {
|
||||
// Update config and save
|
||||
field.setBoolean(ClientConfigManager.getConfig(), value);
|
||||
ClientConfigManager.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for String config options
|
||||
*/
|
||||
private class StringConfigOption extends ConfigOption<String> {
|
||||
private static final int FIELD_WIDTH = 60;
|
||||
private static final int FIELD_HEIGHT = 16;
|
||||
protected TextFieldWidget textField;
|
||||
|
||||
public StringConfigOption(String name, Field field, String initialValue, int x, int y, int width) {
|
||||
super(name, field, initialValue, x, y, width);
|
||||
}
|
||||
|
||||
public void createTextField(net.minecraft.client.MinecraftClient client) {
|
||||
int fieldX = x + width - FIELD_WIDTH - 5;
|
||||
int fieldY = y + (OPTION_HEIGHT - FIELD_HEIGHT) / 2;
|
||||
|
||||
textField = new TextFieldWidget(
|
||||
textRenderer,
|
||||
fieldX,
|
||||
fieldY,
|
||||
FIELD_WIDTH,
|
||||
FIELD_HEIGHT,
|
||||
Text.literal("")
|
||||
);
|
||||
|
||||
textField.setText(value);
|
||||
textField.setMaxLength(10);
|
||||
textField.setChangedListener(this::onTextChanged);
|
||||
}
|
||||
|
||||
public TextFieldWidget getTextField() {
|
||||
return textField;
|
||||
}
|
||||
|
||||
public void updateTextFieldPosition() {
|
||||
if (textField != null) {
|
||||
int fieldX = x + width - FIELD_WIDTH - 5;
|
||||
int fieldY = y + (OPTION_HEIGHT - FIELD_HEIGHT) / 2;
|
||||
textField.setX(fieldX);
|
||||
textField.setY(fieldY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
context.drawText(textRenderer, name, x + 5, y + (OPTION_HEIGHT - 8) / 2, 0xFFFFFF, true);
|
||||
|
||||
if (textField != null) {
|
||||
textField.render(context, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(double mouseX, double mouseY) {
|
||||
}
|
||||
|
||||
public void onTextChanged(String text) {
|
||||
try {
|
||||
value = text;
|
||||
saveValue();
|
||||
} catch (NumberFormatException e) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveValue() {
|
||||
try {
|
||||
field.set(ClientConfigManager.getConfig(), value);
|
||||
ClientConfigManager.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for numeric config options (int and float)
|
||||
*/
|
||||
private abstract class NumericConfigOption<T extends Number> extends ConfigOption<T> {
|
||||
private static final int FIELD_WIDTH = 60;
|
||||
private static final int FIELD_HEIGHT = 16;
|
||||
protected TextFieldWidget textField;
|
||||
|
||||
public NumericConfigOption(String name, Field field, T initialValue, int x, int y, int width) {
|
||||
super(name, field, initialValue, x, y, width);
|
||||
}
|
||||
|
||||
public void createTextField(net.minecraft.client.MinecraftClient client) {
|
||||
int fieldX = x + width - FIELD_WIDTH - 5;
|
||||
int fieldY = y + (OPTION_HEIGHT - FIELD_HEIGHT) / 2;
|
||||
|
||||
textField = new TextFieldWidget(
|
||||
textRenderer,
|
||||
fieldX,
|
||||
fieldY,
|
||||
FIELD_WIDTH,
|
||||
FIELD_HEIGHT,
|
||||
Text.literal("")
|
||||
);
|
||||
|
||||
textField.setText(value.toString());
|
||||
textField.setMaxLength(10);
|
||||
textField.setChangedListener(this::onTextChanged);
|
||||
}
|
||||
|
||||
public TextFieldWidget getTextField() {
|
||||
return textField;
|
||||
}
|
||||
|
||||
public void updateTextFieldPosition() {
|
||||
if (textField != null) {
|
||||
int fieldX = x + width - FIELD_WIDTH - 5;
|
||||
int fieldY = y + (OPTION_HEIGHT - FIELD_HEIGHT) / 2;
|
||||
textField.setX(fieldX);
|
||||
textField.setY(fieldY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
context.drawText(textRenderer, name, x + 5, y + (OPTION_HEIGHT - 8) / 2, 0xFFFFFF, true);
|
||||
|
||||
if (textField != null) {
|
||||
textField.render(context, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(double mouseX, double mouseY) {}
|
||||
|
||||
protected abstract void onTextChanged(String text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for integer config options
|
||||
*/
|
||||
private class IntegerConfigOption extends NumericConfigOption<Integer> {
|
||||
public IntegerConfigOption(String name, Field field, Integer initialValue, int x, int y, int width) {
|
||||
super(name, field, initialValue, x, y, width);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTextChanged(String text) {
|
||||
try {
|
||||
value = Integer.parseInt(text);
|
||||
saveValue();
|
||||
} catch (NumberFormatException e) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveValue() {
|
||||
try {
|
||||
field.setInt(ClientConfigManager.getConfig(), value);
|
||||
ClientConfigManager.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for float config options
|
||||
*/
|
||||
private class FloatConfigOption extends NumericConfigOption<Float> {
|
||||
public FloatConfigOption(String name, Field field, Float initialValue, int x, int y, int width) {
|
||||
super(name, field, initialValue, x, y, width);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTextChanged(String text) {
|
||||
try {
|
||||
value = Float.parseFloat(text);
|
||||
saveValue();
|
||||
} catch (NumberFormatException e) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveValue() {
|
||||
try {
|
||||
field.setFloat(ClientConfigManager.getConfig(), value);
|
||||
ClientConfigManager.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"client": [
|
||||
"BackgroundRendererMixin",
|
||||
"BlockEntityRendererMixin",
|
||||
"EntityMixin"
|
||||
],
|
||||
"injectors": {
|
||||
|
@ -32,7 +32,7 @@ public class SurvivalFabric implements ModInitializer {
|
||||
|
||||
if (getConfig().veinMinerEnabled) {
|
||||
PlayerBlockBreakEvents.BEFORE.register((world, player, pos, state, blockEntity) -> {
|
||||
if (player instanceof ServerPlayerEntity serverPlayer) {
|
||||
if (player instanceof ServerPlayerEntity serverPlayer && getConfig().veinMinerEnabled) {
|
||||
return VeinMinerEvents.beforeBlockBreak(world, serverPlayer, pos, state);
|
||||
} else {
|
||||
return true;
|
||||
|
Reference in New Issue
Block a user