Skip to content
This repository was archived by the owner on Jul 2, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions src/main/java/io/github/solclient/client/SolClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public final class SolClient implements Iterable<Mod> {

public static final SolClient INSTANCE = new SolClient();

private static final Logger LOGGER = LogManager.getLogger();
public static final Logger LOGGER = LogManager.getLogger();
private static final Gson DEFAULT_GSON = getGson(null);

private final List<Mod> mods = new ArrayList<>();
Expand Down Expand Up @@ -165,11 +165,7 @@ public void configure(Mod mod, JsonObject config) {
if (config == null)
return;

try {
getGson(mod).fromJson(config, mod.getClass());
} catch (Throwable error) {
LOGGER.error("Could not configure mod {} on {}", mod.getId(), config, error);
}
mod.loadConfig(config);
}

/**
Expand Down Expand Up @@ -251,10 +247,12 @@ private void prepare(ModInfo info) {
}
}

private static Gson getGson(Mod mod) {
public static Gson getGson(Mod mod) {
GsonBuilder builder = new GsonBuilder();
if (mod != null)
builder.registerTypeAdapter(mod.getClass(), (InstanceCreator<Mod>) (type) -> mod);
if (mod != null) {
builder.registerTypeAdapter(mod.getClass(), (InstanceCreator<Mod>) (type) -> mod);
mod.registerTypeAdapters(builder);
}

return builder.excludeFieldsWithoutExposeAnnotation().create();
}
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/io/github/solclient/client/mod/Mod.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.nio.file.*;
import java.util.*;

import io.github.solclient.client.SolClient;
import org.apache.logging.log4j.*;

import com.google.gson.*;
Expand All @@ -42,6 +43,8 @@
import lombok.*;
import net.minecraft.client.MinecraftClient;

import static io.github.solclient.client.SolClient.getGson;

@AbstractTranslationKey("sol_client.mod.generic")
public abstract class Mod extends Object {

Expand Down Expand Up @@ -337,6 +340,10 @@ public void setPinned(boolean pinned) {
}
}

public void registerTypeAdapters(GsonBuilder builder) {

}

void notifyUnpin() {
pinned = false;
}
Expand All @@ -361,4 +368,11 @@ public void onRender(PostGameOverlayRenderEvent event) {
}
}

public void loadConfig(JsonObject config) {
try {
getGson(this).fromJson(config, getClass());
} catch (Throwable error) {
SolClient.LOGGER.error("Could not configure mod {} on {}", getId(), config, error);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* Sol Client - an open source Minecraft client
* Copyright (C) 2021-2023 TheKodeToad and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package io.github.solclient.client.mod.hud;

import com.google.gson.annotations.Expose;
import com.mojang.blaze3d.platform.GlStateManager;
import com.replaymod.replay.ReplayModReplay;
import io.github.solclient.client.mod.option.ModOption;
import io.github.solclient.client.mod.option.ModOptionStorage;
import io.github.solclient.client.mod.option.impl.SliderOption;
import io.github.solclient.client.util.data.Position;
import io.github.solclient.client.util.data.Rectangle;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.Window;
import net.minecraft.util.math.MathHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public abstract class AbstractHudElement implements HudElement {

public static final String TRANSLATION_KEY = "sol_client.mod.hud";

/** The exact x/y on the screen */
protected Position truePosition = new Position(0, 0);

/** Scaled x/y on screen. Matrices should already be scaled if this is used */
protected Position dividedPosition;

private Rectangle previousBounds = null;

@Expose
protected float x = 0;
@Expose
protected float y = 0;

@Expose
protected float scale = 100;

@Expose
protected AnchorPoint anchorPoint = AnchorPoint.TOP_LEFT;

private int lastWidth = 0;
private int lastHeight = 0;

@Override
public AnchorPoint getAnchor() {
return isDynamic() ? anchorPoint : AnchorPoint.TOP_LEFT;
}

@Override
public List<ModOption<?>> createOptions() {
List<ModOption<?>> options = new ArrayList<>();
options.add(new SliderOption(TRANSLATION_KEY + ".option.scale",
ModOptionStorage.of(Number.class, () -> scale, (value) -> {
if (scale != value.floatValue()) {
scale = value.floatValue();
updateBounds(true);
}
}),
Optional.of("sol_client.slider.percent"), 50, 150, 1));
return options;
}

@Override
public float getScale() {
return scale / 100;
}

public static int floatToInt(float percent, int max, int offset) {
return MathHelper.clamp(Math.round((max - offset) * percent), 0, max);
}

public static float intToFloat(int current, int max, int offset) {
return MathHelper.clamp((float) (current) / (max - offset), 0, 1);
}

public int offsetTrueWidth(boolean editMode) {
return getAnchor().offsetWidth(getMultipliedBounds(editMode).getWidth());
}

public int offsetTrueHeight(boolean editMode) {
return getAnchor().offsetHeight(getMultipliedBounds(editMode).getHeight());
}

@Override
public Position getDividedPosition() {
return dividedPosition;
}

@Override
public Position getConfiguredPosition() {
return truePosition;
}

@Override
public Position getPosition() {
return truePosition;
}

@Override
public void setAnchorPoint(AnchorPoint p) {
this.anchorPoint = p;
}

@Override
public void render(boolean editMode) {
// Don't render HUD in replay or if marked as invisible.
if (!isVisible() || !(editMode || isShownInReplay() || ReplayModReplay.instance.getReplayHandler() == null))
return;

Window window = new Window(MinecraftClient.getInstance());
if ((int) window.getScaledWidth() != lastWidth || (int) window.getScaledHeight() != lastHeight) {
lastWidth = (int) window.getScaledWidth();
lastHeight = (int) window.getScaledHeight();
updateBounds(editMode, lastWidth, lastHeight);
previousBounds = getBounds(editMode);
} else {
Rectangle rect = getBounds(editMode);
if (rect != null) {
if (previousBounds == null) {
previousBounds = updateBounds(editMode);
} else if (rect.getWidth() != previousBounds.getWidth() || rect.getHeight() != previousBounds.getHeight()) {
previousBounds = updateBounds(editMode);
}
}
}

GlStateManager.pushMatrix();
GlStateManager.scale(getScale(), getScale(), getScale());
render(getDividedPosition(), editMode);
GlStateManager.popMatrix();
}

@Override
public void setPosition(Position position, boolean editMode) {
int x = position.getX() + offsetTrueWidth(editMode);
int y = position.getY() + offsetTrueHeight(editMode);
Window window = new Window(MinecraftClient.getInstance());
this.x = intToFloat(x, (int) window.getScaledWidth(), 0);
this.y = intToFloat(y, (int) window.getScaledHeight(), 0);
updateBounds(editMode);
}

@Override
public Rectangle updateBounds(boolean editMode, int scaledWidth, int scaledHeight) {
Rectangle bounds = getBounds(editMode);
if (scaledHeight == 0) {
truePosition = new Position(0, 0);
return truePosition.rectangle(bounds.getWidth(), bounds.getHeight());
}
int scaledX = floatToInt(x, scaledWidth, 0) - offsetTrueWidth(editMode);
int scaledY = floatToInt(y, scaledHeight, 0) - offsetTrueHeight(editMode);
if (scaledX < 0) {
scaledX = 0;
}
if (scaledY < 0) {
scaledY = 0;
}
int trueWidth = (int) (bounds.getWidth() * getScale());
if (trueWidth < scaledWidth && scaledX + trueWidth > scaledWidth) {
scaledX = scaledWidth - trueWidth;
}
int trueHeight = (int) (bounds.getHeight() * getScale());
if (trueHeight < scaledHeight && scaledY + trueHeight > scaledHeight) {
scaledY = scaledHeight - trueHeight;
}
truePosition = new Position(scaledX, scaledY);
dividedPosition = new Position((int) (scaledX / getScale()), (int) (scaledY / getScale()));
return truePosition.rectangle(bounds.getWidth(), bounds.getHeight());
}

}
94 changes: 94 additions & 0 deletions src/main/java/io/github/solclient/client/mod/hud/AnchorPoint.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Sol Client - an open source Minecraft client
* Copyright (C) 2021-2023 TheKodeToad and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package io.github.solclient.client.mod.hud;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Locale;

/**
* Ported here by DarkKronicle from KronHUD by DarkKronicle
* <a href="https://github.com/DarkKronicle/KronHUD">Github</a>
*
* @license GPL-3.0
*/
@AllArgsConstructor
public enum AnchorPoint {

TOP_LEFT(-1, 1),
TOP_MIDDLE(0, 1),
TOP_RIGHT(1, 1),
MIDDLE_LEFT(-1, 0),
MIDDLE_MIDDLE(0, 0),
MIDDLE_RIGHT(1, 0),
BOTTOM_LEFT(-1, -1),
BOTTOM_MIDDLE(0, -1),
BOTTOM_RIGHT(1, -1);

@Getter
private final int xComponent;

@Getter
private final int yComponent;

public int getX(int anchorX, int width) {
switch (xComponent) {
case 0:
return anchorX - (width / 2);
case 1:
return anchorX - width;
default:
return anchorX;
}
}

public int getY(int anchorY, int height) {
switch (yComponent) {
case 0:
return anchorY - (height / 2);
case 1:
return anchorY - height;
default:
return anchorY;
}
}

public int offsetWidth(int width) {
switch (xComponent) {
case 0:
return width / 2;
case 1:
return width;
default:
return 0;
}
}

public int offsetHeight(int height) {
switch (yComponent) {
case 0:
return (height / 2);
case 1:
return 0;
default:
return height;
}
}
}
Loading