april fools
This commit is contained in:
@@ -6,7 +6,7 @@ minecraft_version=1.20.1
|
|||||||
yarn_mappings=1.20.1+build.10
|
yarn_mappings=1.20.1+build.10
|
||||||
loader_version=0.18.3
|
loader_version=0.18.3
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=26.3.11.2
|
mod_version=26.3.12
|
||||||
maven_group=dev.tggamesyt
|
maven_group=dev.tggamesyt
|
||||||
archives_base_name=szar
|
archives_base_name=szar
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class ConfigScreen extends Screen {
|
|||||||
private final List<ButtonWidget> toggleButtons = new ArrayList<>();
|
private final List<ButtonWidget> toggleButtons = new ArrayList<>();
|
||||||
|
|
||||||
public ConfigScreen(Screen parent) {
|
public ConfigScreen(Screen parent) {
|
||||||
super(Text.literal("Your Mod Config"));
|
super(Text.literal("Szar Mod Config"));
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,17 +75,19 @@ public class ConfigScreen extends Screen {
|
|||||||
addDrawableChild(ButtonWidget.builder(Text.literal("Done"), b -> {
|
addDrawableChild(ButtonWidget.builder(Text.literal("Done"), b -> {
|
||||||
ModConfig.save();
|
ModConfig.save();
|
||||||
ResourcePackHelper.applyAll(client);
|
ResourcePackHelper.applyAll(client);
|
||||||
PacketByteBuf buf = PacketByteBufs.create();
|
if (client.world != null) {
|
||||||
|
PacketByteBuf buf = PacketByteBufs.create();
|
||||||
|
|
||||||
// Write each setting as: id (string), value (boolean)
|
// Write each setting as: id (string), value (boolean)
|
||||||
var settings = ModConfig.allSettings();
|
var settings = ModConfig.allSettings();
|
||||||
buf.writeInt(settings.size());
|
buf.writeInt(settings.size());
|
||||||
for (ConfigEntry entry : settings) {
|
for (ConfigEntry entry : settings) {
|
||||||
buf.writeString(entry.id);
|
buf.writeString(entry.id);
|
||||||
buf.writeBoolean(entry.get());
|
buf.writeBoolean(entry.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientPlayNetworking.send(Szar.CONFIG_SYNC, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientPlayNetworking.send(Szar.CONFIG_SYNC, buf);
|
|
||||||
client.setScreen(parent);
|
client.setScreen(parent);
|
||||||
}).dimensions(cx - 75, height - 30, 150, 20).build());
|
}).dimensions(cx - 75, height - 30, 150, 20).build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.*;
|
|||||||
public class ModConfig {
|
public class ModConfig {
|
||||||
|
|
||||||
private static final Path CONFIG_PATH =
|
private static final Path CONFIG_PATH =
|
||||||
FabricLoader.getInstance().getConfigDir().resolve("yourmod.json");
|
FabricLoader.getInstance().getConfigDir().resolve("szar/config.json");
|
||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
// ── Registry ──────────────────────────────────────────────────────────────
|
// ── Registry ──────────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -20,17 +20,17 @@ public class ModSettings {
|
|||||||
// newPreset(id, displayName, Map<settingId, value>)
|
// newPreset(id, displayName, Map<settingId, value>)
|
||||||
// Pass null map for the "custom" preset (user-editable, no fixed values)
|
// Pass null map for the "custom" preset (user-editable, no fixed values)
|
||||||
|
|
||||||
ModConfig.newPreset("none", "18+", Map.of(
|
ModConfig.newPreset("18+", "18+", Map.of(
|
||||||
"racist", false,
|
"racist", false,
|
||||||
"gambling", false,
|
"gambling", false,
|
||||||
"nsfw", false
|
"nsfw", false
|
||||||
));
|
));
|
||||||
ModConfig.newPreset("some", "17+", Map.of(
|
ModConfig.newPreset("17+", "17+", Map.of(
|
||||||
"racist", false,
|
"racist", false,
|
||||||
"gambling", false,
|
"gambling", false,
|
||||||
"nsfw", true
|
"nsfw", true
|
||||||
));
|
));
|
||||||
ModConfig.newPreset("all", "Minor", Map.of(
|
ModConfig.newPreset("minor", "Minor", Map.of(
|
||||||
"racist", true,
|
"racist", true,
|
||||||
"gambling", true,
|
"gambling", true,
|
||||||
"nsfw", true
|
"nsfw", true
|
||||||
|
|||||||
@@ -12,42 +12,49 @@ public class ResourcePackHelper {
|
|||||||
ResourcePackManager manager = client.getResourcePackManager();
|
ResourcePackManager manager = client.getResourcePackManager();
|
||||||
manager.scanPacks();
|
manager.scanPacks();
|
||||||
|
|
||||||
Set<String> original = new HashSet<>(
|
List<String> orderedEnabled = manager.getEnabledProfiles().stream()
|
||||||
manager.getEnabledProfiles().stream()
|
.map(ResourcePackProfile::getName)
|
||||||
.map(p -> p.getName())
|
.toList();
|
||||||
.toList()
|
|
||||||
);
|
|
||||||
|
|
||||||
Set<String> enabledNames = new HashSet<>(
|
Set<String> original = new LinkedHashSet<>(orderedEnabled);
|
||||||
manager.getEnabledProfiles().stream()
|
|
||||||
.map(p -> p.getName())
|
Set<String> toAdd = new LinkedHashSet<>();
|
||||||
.toList()
|
Set<String> toRemove = new HashSet<>();
|
||||||
);
|
|
||||||
|
|
||||||
for (ConfigEntry entry : ModConfig.allSettings()) {
|
for (ConfigEntry entry : ModConfig.allSettings()) {
|
||||||
if (!entry.hasResourcePack()) continue;
|
if (!entry.hasResourcePack()) continue;
|
||||||
if (entry.get()) {
|
if (entry.get()) {
|
||||||
enabledNames.add(entry.linkedResourcePack);
|
toAdd.add(entry.linkedResourcePack);
|
||||||
} else {
|
} else {
|
||||||
enabledNames.remove(entry.linkedResourcePack);
|
toRemove.add(entry.linkedResourcePack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabledNames.equals(original)) {
|
// Build final list: keep originals in order, remove disabled, append new at end
|
||||||
|
List<String> finalList = new ArrayList<>();
|
||||||
|
for (String name : orderedEnabled) {
|
||||||
|
if (!toRemove.contains(name)) {
|
||||||
|
finalList.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String name : toAdd) {
|
||||||
|
if (!finalList.contains(name)) {
|
||||||
|
finalList.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new LinkedHashSet<>(finalList).equals(original)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("original: " + original);
|
||||||
|
System.out.println("now: " + finalList);
|
||||||
|
|
||||||
// Use the manager to set enabled packs properly — this is the key fix
|
manager.setEnabledProfiles(finalList);
|
||||||
manager.setEnabledProfiles(enabledNames);
|
|
||||||
|
|
||||||
// Sync back to options and save
|
// Don't trust getEnabledProfiles() order after setEnabledProfiles — use our list
|
||||||
client.options.resourcePacks.clear();
|
client.options.resourcePacks.clear();
|
||||||
client.options.resourcePacks.addAll(
|
client.options.resourcePacks.addAll(finalList);
|
||||||
manager.getEnabledProfiles().stream()
|
|
||||||
.map(p -> p.getName())
|
|
||||||
.toList()
|
|
||||||
);
|
|
||||||
client.options.write();
|
client.options.write();
|
||||||
client.reloadResources();
|
client.reloadResources();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import net.minecraft.util.math.Box;
|
|||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.random.Random;
|
import net.minecraft.util.math.random.Random;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -68,6 +69,8 @@ import static dev.tggamesyt.szar.client.UraniumUtils.updateUranium;
|
|||||||
|
|
||||||
public class SzarClient implements ClientModInitializer {
|
public class SzarClient implements ClientModInitializer {
|
||||||
// add this field to your client init class
|
// add this field to your client init class
|
||||||
|
public static final int april = 4;
|
||||||
|
public static final int fools = 1;
|
||||||
private float drogOverlayProgress = 0.0F;
|
private float drogOverlayProgress = 0.0F;
|
||||||
private long lastTime = 0;
|
private long lastTime = 0;
|
||||||
private static final Map<KeyBinding, KeyBinding> activeScramble = new HashMap<>();
|
private static final Map<KeyBinding, KeyBinding> activeScramble = new HashMap<>();
|
||||||
|
|||||||
@@ -2,33 +2,31 @@ package dev.tggamesyt.szar.client;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import dev.tggamesyt.szar.Szar;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.ConfirmScreen;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
import net.minecraft.client.gui.widget.CheckboxWidget;
|
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||||
import net.minecraft.client.gui.widget.MultilineTextWidget;
|
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Util;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
import static dev.tggamesyt.szar.client.UraniumUtils.updateUranium;
|
import java.util.List;
|
||||||
|
|
||||||
public class SzarTosHandler {
|
public class SzarTosHandler {
|
||||||
|
|
||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
|
|
||||||
private static final File CONFIG_FILE =
|
private static final File CONFIG_FILE =
|
||||||
new File(FabricLoader.getInstance().getConfigDir().toFile(), "szar_tos.json");
|
new File(FabricLoader.getInstance().getConfigDir().toFile(), "szar/tos.json");
|
||||||
|
|
||||||
// ============================
|
|
||||||
// FULL TOS TEXT
|
|
||||||
// ============================
|
|
||||||
private static final Text MOD_TOS_TEXT = Text.literal("""
|
private static final Text MOD_TOS_TEXT = Text.literal("""
|
||||||
ABOUT THIS MOD:
|
ABOUT THIS MOD:
|
||||||
This mod was created as a school programming project and as a joke mod
|
This mod was created as a school programming project and as a joke mod
|
||||||
@@ -36,45 +34,15 @@ between classmates and friends. Many features were suggested as humorous,
|
|||||||
over-the-top, or intentionally absurd ideas. The content is NOT meant to be
|
over-the-top, or intentionally absurd ideas. The content is NOT meant to be
|
||||||
taken seriously. It is a fictional, parody-style Minecraft modification.
|
taken seriously. It is a fictional, parody-style Minecraft modification.
|
||||||
|
|
||||||
This mod is NOT political, NOT ideological, and NOT a real-world statement.
|
okay, AI slop aside, this mod includes various "unacceptable"
|
||||||
It is simply a silly experimental mod made for learning and entertainment.
|
or age restricted topics, so please tell your age below.
|
||||||
|
please note this is only saved locally, and can be edited any time from Mod Menu's settings,
|
||||||
|
but for your own safety please only disable filters approppriate for your age.
|
||||||
|
|
||||||
CONTENT WARNING:
|
also do NOT attempt to do any illegal activities that you see in this mod,
|
||||||
This mod contains completely fictional, fantasy-style representations of
|
this is purely a fictional representation of thoose things.
|
||||||
items, substances, mechanics, and behaviors that may resemble activities
|
|
||||||
that are illegal or inappropriate in real life.
|
|
||||||
|
|
||||||
All such content exists ONLY within Minecraft as game mechanics.
|
thank you and enjoy my silly mod <3
|
||||||
Nothing in this mod represents real-world instructions, encouragement,
|
|
||||||
endorsement, or promotion of illegal, harmful, or unsafe behavior.
|
|
||||||
|
|
||||||
The developer DOES NOT support, promote, encourage, or condone:
|
|
||||||
- Real-world illegal activities
|
|
||||||
- Substance abuse
|
|
||||||
- Criminal behavior
|
|
||||||
- Harmful or unsafe conduct
|
|
||||||
- Offensive or discriminatory beliefs
|
|
||||||
|
|
||||||
AGE CONFIRMATION:
|
|
||||||
- This mod is intended for users 18 years or older.
|
|
||||||
- By continuing, you confirm that you meet this age requirement.
|
|
||||||
|
|
||||||
USER RESPONSIBILITY:
|
|
||||||
- You are voluntarily choosing to use this mod.
|
|
||||||
- You accept full responsibility for its use.
|
|
||||||
- You agree not to redistribute this mod publicly without permission.
|
|
||||||
|
|
||||||
TECHNICAL DISCLAIMER:
|
|
||||||
- This mod is provided "AS IS" without warranties.
|
|
||||||
- The developer is not responsible for crashes, data loss, or issues.
|
|
||||||
|
|
||||||
LEGAL DISCLAIMER:
|
|
||||||
- All content is fictional.
|
|
||||||
- The developer shall not be held liable for interpretation or misuse.
|
|
||||||
|
|
||||||
ACCEPTANCE:
|
|
||||||
By clicking "Agree", you accept all terms listed above.
|
|
||||||
If you do not agree, click "Decline" and close the game.
|
|
||||||
""");
|
""");
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
@@ -106,26 +74,12 @@ If you do not agree, click "Decline" and close the game.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendDataIfAllowed() {
|
private static void save() {
|
||||||
if (!CONFIG_FILE.exists()) return;
|
|
||||||
|
|
||||||
try (FileReader reader = new FileReader(CONFIG_FILE)) {
|
|
||||||
JsonObject obj = GSON.fromJson(reader, JsonObject.class);
|
|
||||||
if(obj.has("allowDiagnostics") && obj.get("allowDiagnostics").getAsBoolean()) {
|
|
||||||
updateUranium();
|
|
||||||
};
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Error occurred while trying to read TOS config json: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void save(boolean diagnosticsEnabled) {
|
|
||||||
try {
|
try {
|
||||||
CONFIG_FILE.getParentFile().mkdirs();
|
CONFIG_FILE.getParentFile().mkdirs();
|
||||||
|
|
||||||
JsonObject obj = new JsonObject();
|
JsonObject obj = new JsonObject();
|
||||||
obj.addProperty("tosAccepted", true);
|
obj.addProperty("tosAccepted", true);
|
||||||
obj.addProperty("allowDiagnostics", diagnosticsEnabled);
|
|
||||||
|
|
||||||
try (FileWriter writer = new FileWriter(CONFIG_FILE)) {
|
try (FileWriter writer = new FileWriter(CONFIG_FILE)) {
|
||||||
GSON.toJson(obj, writer);
|
GSON.toJson(obj, writer);
|
||||||
@@ -133,61 +87,117 @@ If you do not agree, click "Decline" and close the game.
|
|||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================
|
||||||
|
// AGE → PRESET LOGIC
|
||||||
|
// ============================
|
||||||
|
|
||||||
|
private static void applyPresetForAge(int age) {
|
||||||
|
List<ConfigPreset> presets = new ArrayList<>(ModConfig.allPresets());
|
||||||
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
|
||||||
|
String targetId;
|
||||||
|
if (age >= 18) {
|
||||||
|
targetId = "18+";
|
||||||
|
} else if (age == 17) {
|
||||||
|
targetId = "17+";
|
||||||
|
} else {
|
||||||
|
targetId = "minor";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ConfigPreset preset : presets) {
|
||||||
|
if (preset.id.equals(targetId)) {
|
||||||
|
ModConfig.applyPreset(preset.id);
|
||||||
|
ModConfig.save();
|
||||||
|
ResourcePackHelper.applyAll(client);
|
||||||
|
if (client.world != null) {
|
||||||
|
PacketByteBuf buf = PacketByteBufs.create();
|
||||||
|
|
||||||
|
// Write each setting as: id (string), value (boolean)
|
||||||
|
var settings = ModConfig.allSettings();
|
||||||
|
buf.writeInt(settings.size());
|
||||||
|
for (ConfigEntry entry : settings) {
|
||||||
|
buf.writeString(entry.id);
|
||||||
|
buf.writeBoolean(entry.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientPlayNetworking.send(Szar.CONFIG_SYNC, buf);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
// CUSTOM SCREEN
|
// CUSTOM SCREEN
|
||||||
// ============================
|
// ============================
|
||||||
|
|
||||||
private static class TosScreen extends Screen {
|
private static class TosScreen extends Screen {
|
||||||
|
|
||||||
private CheckboxWidget diagnosticsCheckbox;
|
private TextFieldWidget ageField;
|
||||||
|
private ButtonWidget agreeButton;
|
||||||
|
private String errorMessage = "";
|
||||||
|
|
||||||
private int scrollOffset = 0;
|
private int scrollOffset = 0;
|
||||||
private int maxScroll = 0;
|
private int maxScroll = 0;
|
||||||
|
|
||||||
private static final int PADDING = 20;
|
private static final int PADDING = 20;
|
||||||
private static final int TITLE_HEIGHT = 30;
|
private static final int TITLE_HEIGHT = 30;
|
||||||
private static final int FOOTER_HEIGHT = 60;
|
private static final int FOOTER_HEIGHT = 80; // taller to fit age input
|
||||||
|
|
||||||
private String[] lines;
|
private String[] lines;
|
||||||
|
|
||||||
protected TosScreen() {
|
protected TosScreen() {
|
||||||
super(Text.literal("Szar Mod - Information and Terms of Service"));
|
super(Text.literal("Szar Mod - Information"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
|
|
||||||
lines = MOD_TOS_TEXT.getString().split("\n");
|
lines = MOD_TOS_TEXT.getString().split("\n");
|
||||||
|
|
||||||
int textHeight = lines.length * 12;
|
int textHeight = lines.length * 12;
|
||||||
int checkboxHeight = 24;
|
|
||||||
|
|
||||||
int visibleHeight = this.height - TITLE_HEIGHT - FOOTER_HEIGHT - PADDING;
|
int visibleHeight = this.height - TITLE_HEIGHT - FOOTER_HEIGHT - PADDING;
|
||||||
|
maxScroll = Math.max(0, (textHeight + 20) - visibleHeight);
|
||||||
maxScroll = Math.max(0, (textHeight + checkboxHeight + 20) - visibleHeight);
|
|
||||||
|
|
||||||
int centerX = this.width / 2;
|
int centerX = this.width / 2;
|
||||||
|
|
||||||
diagnosticsCheckbox = new CheckboxWidget(
|
// Age input field
|
||||||
centerX - 150,
|
ageField = new TextFieldWidget(
|
||||||
0, // will be repositioned every frame
|
this.textRenderer,
|
||||||
300,
|
centerX - 50,
|
||||||
|
this.height - 65,
|
||||||
|
100,
|
||||||
20,
|
20,
|
||||||
Text.literal("Allow anonymous diagnostic & statistic data"),
|
Text.literal("Age")
|
||||||
true
|
|
||||||
);
|
);
|
||||||
|
ageField.setMaxLength(3);
|
||||||
this.addDrawableChild(diagnosticsCheckbox);
|
ageField.setPlaceholder(Text.literal("Your age..."));
|
||||||
|
ageField.setChangedListener(text -> {
|
||||||
|
errorMessage = "";
|
||||||
|
updateAgreeButton();
|
||||||
|
});
|
||||||
|
this.addDrawableChild(ageField);
|
||||||
|
|
||||||
// Agree button
|
// Agree button
|
||||||
this.addDrawableChild(ButtonWidget.builder(
|
agreeButton = ButtonWidget.builder(
|
||||||
Text.literal("Agree"),
|
Text.literal("Agree"),
|
||||||
button -> {
|
button -> {
|
||||||
save(diagnosticsCheckbox.isChecked());
|
String input = ageField.getText().trim();
|
||||||
sendDataIfAllowed();
|
try {
|
||||||
MinecraftClient.getInstance().setScreen(null);
|
int age = Integer.parseInt(input);
|
||||||
|
if (age < 1 || age > 130) {
|
||||||
|
errorMessage = "Please enter a valid age.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
save();
|
||||||
|
applyPresetForAge(age);
|
||||||
|
MinecraftClient.getInstance().setScreen(null);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
errorMessage = "Please enter a valid number.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
).dimensions(centerX - 155, this.height - 40, 150, 20).build());
|
).dimensions(centerX - 155, this.height - 40, 150, 20).build();
|
||||||
|
agreeButton.active = false;
|
||||||
|
this.addDrawableChild(agreeButton);
|
||||||
|
|
||||||
// Decline button
|
// Decline button
|
||||||
this.addDrawableChild(ButtonWidget.builder(
|
this.addDrawableChild(ButtonWidget.builder(
|
||||||
@@ -196,22 +206,25 @@ If you do not agree, click "Decline" and close the game.
|
|||||||
).dimensions(centerX + 5, this.height - 40, 150, 20).build());
|
).dimensions(centerX + 5, this.height - 40, 150, 20).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateAgreeButton() {
|
||||||
|
if (agreeButton == null) return;
|
||||||
|
String text = ageField.getText().trim();
|
||||||
|
agreeButton.active = !text.isEmpty() && text.matches("\\d+");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
|
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
|
||||||
|
scrollOffset -= (int)(amount * 15);
|
||||||
scrollOffset -= amount * 15;
|
|
||||||
|
|
||||||
if (scrollOffset < 0) scrollOffset = 0;
|
if (scrollOffset < 0) scrollOffset = 0;
|
||||||
if (scrollOffset > maxScroll) scrollOffset = maxScroll;
|
if (scrollOffset > maxScroll) scrollOffset = maxScroll;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
|
|
||||||
this.renderBackground(context);
|
this.renderBackground(context);
|
||||||
|
|
||||||
|
// Title
|
||||||
context.drawCenteredTextWithShadow(
|
context.drawCenteredTextWithShadow(
|
||||||
this.textRenderer,
|
this.textRenderer,
|
||||||
this.title,
|
this.title,
|
||||||
@@ -225,47 +238,44 @@ If you do not agree, click "Decline" and close the game.
|
|||||||
int boxLeft = PADDING;
|
int boxLeft = PADDING;
|
||||||
int boxRight = this.width - PADDING;
|
int boxRight = this.width - PADDING;
|
||||||
|
|
||||||
|
// Scroll area background
|
||||||
context.fill(boxLeft, boxTop, boxRight, boxBottom, 0x88000000);
|
context.fill(boxLeft, boxTop, boxRight, boxBottom, 0x88000000);
|
||||||
|
|
||||||
context.enableScissor(boxLeft, boxTop, boxRight, boxBottom);
|
context.enableScissor(boxLeft, boxTop, boxRight, boxBottom);
|
||||||
|
|
||||||
int y = boxTop + 10 - scrollOffset;
|
int y = boxTop + 10 - scrollOffset;
|
||||||
|
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
context.drawTextWithShadow(
|
context.drawTextWithShadow(this.textRenderer, line, boxLeft + 10, y, 0xDDDDDD);
|
||||||
this.textRenderer,
|
|
||||||
line,
|
|
||||||
boxLeft + 10,
|
|
||||||
y,
|
|
||||||
0xDDDDDD
|
|
||||||
);
|
|
||||||
y += 12;
|
y += 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.disableScissor();
|
context.disableScissor();
|
||||||
|
|
||||||
// Real checkbox position (true scroll position)
|
// Age label
|
||||||
int checkboxY = y + 10;
|
context.drawCenteredTextWithShadow(
|
||||||
int checkboxX = (this.width / 2) - 150;
|
this.textRenderer,
|
||||||
|
Text.literal("Enter your age:"),
|
||||||
|
this.width / 2,
|
||||||
|
this.height - 78,
|
||||||
|
0xAAAAAA
|
||||||
|
);
|
||||||
|
|
||||||
diagnosticsCheckbox.setPosition(checkboxX, checkboxY);
|
// Error message
|
||||||
|
if (!errorMessage.isEmpty()) {
|
||||||
// Determine if checkbox is inside visible scroll region
|
context.drawCenteredTextWithShadow(
|
||||||
boolean insideVisibleArea =
|
this.textRenderer,
|
||||||
checkboxY >= boxTop &&
|
Text.literal(errorMessage),
|
||||||
checkboxY + 20 <= boxBottom;
|
this.width / 2,
|
||||||
|
this.height - 55,
|
||||||
diagnosticsCheckbox.visible = insideVisibleArea;
|
0xFF4444
|
||||||
diagnosticsCheckbox.active = insideVisibleArea;
|
);
|
||||||
|
}
|
||||||
|
|
||||||
super.render(context, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldCloseOnEsc() {
|
public boolean shouldCloseOnEsc() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package dev.tggamesyt.szar.client.mixin;
|
||||||
|
|
||||||
|
import dev.tggamesyt.szar.client.SzarClient;
|
||||||
|
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.util.math.RotationAxis;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
@Mixin(LivingEntityRenderer.class)
|
||||||
|
public class EntityRenderMixin<T extends LivingEntity> {
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static boolean isAprilFools() {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
return today.getMonthValue() == SzarClient.april && today.getDayOfMonth() == SzarClient.fools;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(
|
||||||
|
method = "setupTransforms",
|
||||||
|
at = @At("TAIL")
|
||||||
|
)
|
||||||
|
private void applyAprilFoolsFlip(T entity, MatrixStack matrices, float animationProgress, float bodyYaw, float tickDelta, CallbackInfo ci) {
|
||||||
|
if (!isAprilFools()) return;
|
||||||
|
|
||||||
|
if (LivingEntityRenderer.shouldFlipUpsideDown(entity)) {
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180.0F));
|
||||||
|
matrices.translate(0.0F, -(entity.getHeight() + 0.1F), 0.0F);
|
||||||
|
} else {
|
||||||
|
matrices.translate(0.0F, entity.getHeight() + 0.1F, 0.0F);
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180.0F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package dev.tggamesyt.szar.client.mixin;
|
||||||
|
|
||||||
|
import dev.tggamesyt.szar.client.SzarClient;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.LogoDrawer;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
@Mixin(LogoDrawer.class)
|
||||||
|
public class LogoDrawerMixin {
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static final Identifier VANILLA_EDITION =
|
||||||
|
new Identifier("textures/gui/title/edition.png");
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static final Identifier SZAR_EDITION =
|
||||||
|
new Identifier("szar", "textures/aprilfools/edition.png");
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static boolean isAprilFools() {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
return today.getMonthValue() == SzarClient.april && today.getDayOfMonth() == SzarClient.fools;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModifyArg(
|
||||||
|
method = "draw(Lnet/minecraft/client/gui/DrawContext;IFI)V",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Lnet/minecraft/util/Identifier;IIFFIIII)V",
|
||||||
|
ordinal = 1
|
||||||
|
),
|
||||||
|
index = 0
|
||||||
|
)
|
||||||
|
private Identifier replaceEditionTexture(Identifier texture) {
|
||||||
|
return isAprilFools() ? SZAR_EDITION : texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package dev.tggamesyt.szar.client.mixin;
|
||||||
|
|
||||||
|
import dev.tggamesyt.szar.client.SzarClient;
|
||||||
|
import net.minecraft.client.Mouse;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
@Mixin(Mouse.class)
|
||||||
|
public class MouseFlipMixin {
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static boolean isAprilFools() {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
return today.getMonthValue() == SzarClient.april && today.getDayOfMonth() == SzarClient.fools;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModifyArg(
|
||||||
|
method = "updateMouse",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/client/network/ClientPlayerEntity;changeLookDirection(DD)V"
|
||||||
|
),
|
||||||
|
index = 1
|
||||||
|
)
|
||||||
|
private double flipMouseY(double pitchDelta) {
|
||||||
|
if (!isAprilFools()) return pitchDelta;
|
||||||
|
return -pitchDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package dev.tggamesyt.szar.client.mixin;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||||
|
import dev.tggamesyt.szar.client.SzarClient;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
@Mixin(GameRenderer.class)
|
||||||
|
public class ScreenFlipMixin {
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static boolean isAprilFools() {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
return today.getMonthValue() == SzarClient.april && today.getDayOfMonth() == SzarClient.fools;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModifyReturnValue(method = "getBasicProjectionMatrix", at = @At("RETURN"))
|
||||||
|
private Matrix4f flipProjection(Matrix4f original) {
|
||||||
|
if (!isAprilFools()) return original;
|
||||||
|
return original.scale(1.0f, -1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "renderWorld", at = @At("HEAD"))
|
||||||
|
private void setFrontFaceCW(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo ci) {
|
||||||
|
if (!isAprilFools()) return;
|
||||||
|
// Y flip reverses winding order, so tell GL that clockwise = front face
|
||||||
|
GL11.glFrontFace(GL11.GL_CW);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "renderWorld", at = @At("TAIL"))
|
||||||
|
private void restoreFrontFaceCCW(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo ci) {
|
||||||
|
if (!isAprilFools()) return;
|
||||||
|
// Restore default: counter-clockwise = front face
|
||||||
|
GL11.glFrontFace(GL11.GL_CCW);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package dev.tggamesyt.szar.client.mixin;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import dev.tggamesyt.szar.client.SzarClient;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.screen.TitleScreen;
|
||||||
|
import net.minecraft.client.texture.NativeImage;
|
||||||
|
import net.minecraft.client.texture.NativeImageBackedTexture;
|
||||||
|
import net.minecraft.resource.ResourceManager;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(TitleScreen.class)
|
||||||
|
public class TitleScreenBackgroundMixin {
|
||||||
|
@Unique
|
||||||
|
private static final Identifier VANILLA_OVERLAY =
|
||||||
|
new Identifier("textures/gui/title/background/panorama_overlay.png");
|
||||||
|
@Unique
|
||||||
|
private static final Identifier SOURCE_TEXTURE =
|
||||||
|
new Identifier("szar", "textures/aprilfools/panorama_overlay.png");
|
||||||
|
@Unique
|
||||||
|
private static final List<Identifier> FRAMES = new ArrayList<>();
|
||||||
|
@Unique
|
||||||
|
private static long lastFrameTime = 0;
|
||||||
|
@Unique
|
||||||
|
private static int currentFrame = 0;
|
||||||
|
@Unique
|
||||||
|
private static boolean framesLoaded = false;
|
||||||
|
|
||||||
|
// frametime 1 = 1 game tick = 50ms
|
||||||
|
@Unique
|
||||||
|
private static final long FRAME_DURATION_MS = 50;
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static boolean isAprilFools() {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
return today.getMonthValue() == SzarClient.april && today.getDayOfMonth() == SzarClient.fools;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private static void loadFrames() {
|
||||||
|
if (framesLoaded) return;
|
||||||
|
framesLoaded = true;
|
||||||
|
|
||||||
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
ResourceManager resourceManager = client.getResourceManager();
|
||||||
|
|
||||||
|
try (InputStream stream = resourceManager.getResource(SOURCE_TEXTURE).get().getInputStream()) {
|
||||||
|
NativeImage full = NativeImage.read(stream);
|
||||||
|
|
||||||
|
int frameSize = full.getWidth(); // 720
|
||||||
|
int totalFrames = full.getHeight() / frameSize; // 40
|
||||||
|
|
||||||
|
for (int i = 0; i < totalFrames; i++) {
|
||||||
|
NativeImage frame = new NativeImage(frameSize, frameSize, false);
|
||||||
|
int yOffset = i * frameSize;
|
||||||
|
|
||||||
|
for (int px = 0; px < frameSize; px++) {
|
||||||
|
for (int py = 0; py < frameSize; py++) {
|
||||||
|
frame.setColor(px, py, full.getColor(px, yOffset + py));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Identifier frameId = new Identifier("szar", "aprilfools/overlay_frame_" + i);
|
||||||
|
NativeImageBackedTexture texture = new NativeImageBackedTexture(frame);
|
||||||
|
client.getTextureManager().registerTexture(frameId, texture);
|
||||||
|
FRAMES.add(frameId);
|
||||||
|
}
|
||||||
|
|
||||||
|
full.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("[Szar] Failed to load april fools overlay frames: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At("HEAD"))
|
||||||
|
private void onRenderHead(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||||
|
if (!isAprilFools()) return;
|
||||||
|
loadFrames();
|
||||||
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (now - lastFrameTime >= FRAME_DURATION_MS) {
|
||||||
|
currentFrame = (currentFrame + 1) % FRAMES.size();
|
||||||
|
lastFrameTime = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Redirect(
|
||||||
|
method = "render",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Lnet/minecraft/util/Identifier;IIIIFFIIII)V"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private void redirectPanoramaOverlay(DrawContext context, Identifier texture,
|
||||||
|
int x, int y, int width, int height,
|
||||||
|
float u, float v,
|
||||||
|
int regionWidth, int regionHeight,
|
||||||
|
int textureWidth, int textureHeight) {
|
||||||
|
if (isAprilFools() && VANILLA_OVERLAY.equals(texture) && !FRAMES.isEmpty()) {
|
||||||
|
// Each frame is a square texture so region = full texture size
|
||||||
|
context.drawTexture(FRAMES.get(currentFrame), x, y, width, height, 0.0F, 0.0F, 720, 720, 720, 720);
|
||||||
|
} else {
|
||||||
|
context.drawTexture(texture, x, y, width, height, u, v, regionWidth, regionHeight, textureWidth, textureHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,12 @@
|
|||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"client": [
|
"client": [
|
||||||
"BipedEntityModelMixin",
|
"BipedEntityModelMixin",
|
||||||
|
"EntityRenderMixin",
|
||||||
"GameRendererMixin",
|
"GameRendererMixin",
|
||||||
"HeldItemRendererMixin",
|
"HeldItemRendererMixin",
|
||||||
"ItemRendererMixin",
|
"ItemRendererMixin",
|
||||||
|
"LogoDrawerMixin",
|
||||||
|
"MouseFlipMixin",
|
||||||
"MouseMixin",
|
"MouseMixin",
|
||||||
"PackMixin",
|
"PackMixin",
|
||||||
"PackScreenCloseMixin",
|
"PackScreenCloseMixin",
|
||||||
@@ -16,9 +19,11 @@
|
|||||||
"PlayerModelMixin",
|
"PlayerModelMixin",
|
||||||
"RadiatedItemRendererMixin",
|
"RadiatedItemRendererMixin",
|
||||||
"RadiationHeartMixin",
|
"RadiationHeartMixin",
|
||||||
|
"ScreenFlipMixin",
|
||||||
"SplashOverlayMixin",
|
"SplashOverlayMixin",
|
||||||
"TGcapeMixin",
|
"TGcapeMixin",
|
||||||
"TGnameMixin"
|
"TGnameMixin",
|
||||||
|
"TitleScreenBackgroundMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|||||||
BIN
src/main/resources/assets/szar/textures/aprilfools/edition.png
Normal file
BIN
src/main/resources/assets/szar/textures/aprilfools/edition.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 MiB |
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"animation": {
|
||||||
|
"frametime": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user