fahh
@@ -29,6 +29,10 @@ fabricApi {
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "Terraformers"
|
||||
url = "https://maven.terraformersmc.com/"
|
||||
}
|
||||
// Add repositories to retrieve artifacts from in here.
|
||||
// You should only use this when depending on other mods because
|
||||
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
|
||||
@@ -43,6 +47,8 @@ dependencies {
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
|
||||
modImplementation("com.terraformersmc:modmenu:${project.modmenu_version}")
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
||||
@@ -6,9 +6,10 @@ minecraft_version=1.20.1
|
||||
yarn_mappings=1.20.1+build.10
|
||||
loader_version=0.18.3
|
||||
# Mod Properties
|
||||
mod_version=26.3.11.1
|
||||
mod_version=26.3.11.2
|
||||
maven_group=dev.tggamesyt
|
||||
archives_base_name=szar
|
||||
# Dependencies
|
||||
# check this on https://modmuss50.me/fabric.html
|
||||
fabric_version=0.92.6+1.20.1
|
||||
modmenu_version=7.2.2
|
||||
|
||||
27
src/client/java/dev/tggamesyt/szar/client/ConfigEntry.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
public class ConfigEntry {
|
||||
public final String id;
|
||||
public final String displayName;
|
||||
public final boolean defaultValue;
|
||||
public final String linkedResourcePack; // null if no resourcepack linked
|
||||
|
||||
private boolean value;
|
||||
|
||||
public ConfigEntry(String id, String displayName, boolean defaultValue, String linkedResourcePack) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.defaultValue = defaultValue;
|
||||
this.linkedResourcePack = linkedResourcePack;
|
||||
this.value = defaultValue;
|
||||
}
|
||||
|
||||
// Convenience constructor — no resourcepack
|
||||
public ConfigEntry(String id, String displayName, boolean defaultValue) {
|
||||
this(id, displayName, defaultValue, null);
|
||||
}
|
||||
|
||||
public boolean get() { return value; }
|
||||
public void set(boolean v) { value = v; }
|
||||
public boolean hasResourcePack() { return linkedResourcePack != null; }
|
||||
}
|
||||
17
src/client/java/dev/tggamesyt/szar/client/ConfigPreset.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigPreset {
|
||||
public final String id;
|
||||
public final String displayName;
|
||||
public final Map<String, Boolean> values; // setting id → value, null means "leave as-is" (custom)
|
||||
|
||||
public ConfigPreset(String id, String displayName, Map<String, Boolean> values) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.values = values; // null map = Custom preset
|
||||
}
|
||||
|
||||
public boolean isCustom() { return values == null; }
|
||||
}
|
||||
145
src/client/java/dev/tggamesyt/szar/client/ConfigScreen.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import dev.tggamesyt.szar.Szar;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ConfigScreen extends Screen {
|
||||
|
||||
private final Screen parent;
|
||||
private final List<ButtonWidget> presetButtons = new ArrayList<>();
|
||||
private final List<ButtonWidget> toggleButtons = new ArrayList<>();
|
||||
|
||||
public ConfigScreen(Screen parent) {
|
||||
super(Text.literal("Your Mod Config"));
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
int cx = width / 2;
|
||||
int y = 40;
|
||||
|
||||
// ── Preset buttons ────────────────────────────────────────────────────
|
||||
List<ConfigPreset> presets = new ArrayList<>(ModConfig.allPresets());
|
||||
int btnW = Math.min(70, (width - 40) / presets.size() - 4);
|
||||
int total = presets.size() * (btnW + 4);
|
||||
int px = cx - total / 2;
|
||||
|
||||
presetButtons.clear();
|
||||
for (ConfigPreset preset : presets) {
|
||||
int bx = px;
|
||||
ButtonWidget btn = ButtonWidget.builder(
|
||||
presetButtonLabel(preset),
|
||||
b -> {
|
||||
ModConfig.applyPreset(preset.id);
|
||||
refreshPresetButtons();
|
||||
refreshToggles();
|
||||
})
|
||||
.dimensions(bx, y, btnW, 20)
|
||||
.build();
|
||||
addDrawableChild(btn);
|
||||
presetButtons.add(btn);
|
||||
px += btnW + 4;
|
||||
}
|
||||
y += 34;
|
||||
|
||||
// ── Toggle buttons — generated from registered settings ───────────────
|
||||
toggleButtons.clear();
|
||||
for (ConfigEntry entry : ModConfig.allSettings()) {
|
||||
ButtonWidget btn = ButtonWidget.builder(
|
||||
toggleLabel(entry),
|
||||
b -> {
|
||||
ModConfig.setAndMarkCustom(entry.id, !entry.get());
|
||||
b.setMessage(toggleLabel(entry));
|
||||
refreshPresetButtons(); // update custom highlight
|
||||
})
|
||||
.dimensions(cx - 100, y, 200, 20)
|
||||
.build();
|
||||
addDrawableChild(btn);
|
||||
toggleButtons.add(btn);
|
||||
y += 26;
|
||||
}
|
||||
|
||||
refreshPresetButtons();
|
||||
refreshToggles();
|
||||
|
||||
// ── Done ──────────────────────────────────────────────────────────────
|
||||
addDrawableChild(ButtonWidget.builder(Text.literal("Done"), b -> {
|
||||
ModConfig.save();
|
||||
ResourcePackHelper.applyAll(client);
|
||||
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);
|
||||
client.setScreen(parent);
|
||||
}).dimensions(cx - 75, height - 30, 150, 20).build());
|
||||
}
|
||||
|
||||
private void refreshPresetButtons() {
|
||||
List<ConfigPreset> presets = new ArrayList<>(ModConfig.allPresets());
|
||||
for (int i = 0; i < presetButtons.size(); i++) {
|
||||
presetButtons.get(i).setMessage(presetButtonLabel(presets.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshToggles() {
|
||||
boolean isCustom = PRESETS.values().stream()
|
||||
.filter(ConfigPreset::isCustom)
|
||||
.anyMatch(p -> p.id.equals(ModConfig.getActivePresetId()));
|
||||
|
||||
List<ConfigEntry> entries = new ArrayList<>(ModConfig.allSettings());
|
||||
for (int i = 0; i < toggleButtons.size(); i++) {
|
||||
ConfigEntry entry = entries.get(i);
|
||||
toggleButtons.get(i).active = isCustom;
|
||||
toggleButtons.get(i).setMessage(toggleLabel(entry));
|
||||
}
|
||||
}
|
||||
|
||||
// Grab presets map for isCustom check
|
||||
private static final java.util.LinkedHashMap<String, ConfigPreset> PRESETS;
|
||||
static {
|
||||
try {
|
||||
var field = ModConfig.class.getDeclaredField("PRESETS");
|
||||
field.setAccessible(true);
|
||||
//noinspection unchecked
|
||||
PRESETS = (java.util.LinkedHashMap<String, ConfigPreset>) field.get(null);
|
||||
} catch (Exception e) { throw new RuntimeException(e); }
|
||||
}
|
||||
|
||||
private Text presetButtonLabel(ConfigPreset preset) {
|
||||
boolean active = preset.id.equals(ModConfig.getActivePresetId());
|
||||
return active
|
||||
? Text.literal("§e[" + preset.displayName + "]§r")
|
||||
: Text.literal(preset.displayName);
|
||||
}
|
||||
|
||||
private Text toggleLabel(ConfigEntry entry) {
|
||||
return Text.literal(entry.displayName + ": " + (entry.get() ? "§aON§r" : "§cOFF§r"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext ctx, int mouseX, int mouseY, float delta) {
|
||||
renderBackground(ctx);
|
||||
ctx.drawCenteredTextWithShadow(textRenderer, title, width / 2, 15, 0xFFFFFF);
|
||||
ctx.drawTextWithShadow(textRenderer, Text.literal("§7Preset:"), width / 2 - 130, 43, 0xAAAAAA);
|
||||
super.render(ctx, mouseX, mouseY, delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() { client.setScreen(parent); }
|
||||
}
|
||||
120
src/client/java/dev/tggamesyt/szar/client/ModConfig.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import com.google.gson.*;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
|
||||
public class ModConfig {
|
||||
|
||||
private static final Path CONFIG_PATH =
|
||||
FabricLoader.getInstance().getConfigDir().resolve("yourmod.json");
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
// ── Registry ──────────────────────────────────────────────────────────────
|
||||
private static final LinkedHashMap<String, ConfigEntry> SETTINGS = new LinkedHashMap<>();
|
||||
private static final LinkedHashMap<String, ConfigPreset> PRESETS = new LinkedHashMap<>();
|
||||
private static String activePresetId = null;
|
||||
|
||||
// ── Registration API ──────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Register a toggle setting.
|
||||
* @param id Unique ID, used in save file and code
|
||||
* @param displayName Label shown in the config screen
|
||||
* @param defaultValue Default on/off state
|
||||
* @param resourcePackId Resource pack to enable/disable with this setting, or null
|
||||
*/
|
||||
public static ConfigEntry newSetting(String id, String displayName,
|
||||
boolean defaultValue, String resourcePackId) {
|
||||
ConfigEntry entry = new ConfigEntry(id, displayName, defaultValue, resourcePackId);
|
||||
SETTINGS.put(id, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/** Register a toggle setting with no linked resource pack. */
|
||||
public static ConfigEntry newSetting(String id, String displayName, boolean defaultValue) {
|
||||
return newSetting(id, displayName, defaultValue, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a preset.
|
||||
* @param id Unique ID
|
||||
* @param displayName Label shown on the button
|
||||
* @param values Map of setting id → value. Pass null to make this the "Custom" preset.
|
||||
*/
|
||||
public static ConfigPreset newPreset(String id, String displayName, Map<String, Boolean> values) {
|
||||
ConfigPreset preset = new ConfigPreset(id, displayName, values);
|
||||
PRESETS.put(id, preset);
|
||||
if (activePresetId == null) activePresetId = id; // first preset is default
|
||||
return preset;
|
||||
}
|
||||
|
||||
// ── Accessors ─────────────────────────────────────────────────────────────
|
||||
|
||||
public static boolean get(String settingId) {
|
||||
ConfigEntry e = SETTINGS.get(settingId);
|
||||
if (e == null) throw new IllegalArgumentException("Unknown setting: " + settingId);
|
||||
return e.get();
|
||||
}
|
||||
|
||||
public static Collection<ConfigEntry> allSettings() { return SETTINGS.values(); }
|
||||
public static Collection<ConfigPreset> allPresets() { return PRESETS.values(); }
|
||||
|
||||
public static String getActivePresetId() { return activePresetId; }
|
||||
|
||||
public static void applyPreset(String presetId) {
|
||||
ConfigPreset preset = PRESETS.get(presetId);
|
||||
if (preset == null) throw new IllegalArgumentException("Unknown preset: " + presetId);
|
||||
activePresetId = presetId;
|
||||
if (!preset.isCustom()) {
|
||||
preset.values.forEach((id, val) -> {
|
||||
ConfigEntry e = SETTINGS.get(id);
|
||||
if (e != null) e.set(val);
|
||||
});
|
||||
}
|
||||
// Custom preset: leave all values as-is
|
||||
}
|
||||
|
||||
/** Call this when the user manually changes a toggle — auto-switches to the custom preset. */
|
||||
public static void setAndMarkCustom(String settingId, boolean value) {
|
||||
ConfigEntry e = SETTINGS.get(settingId);
|
||||
if (e == null) throw new IllegalArgumentException("Unknown setting: " + settingId);
|
||||
e.set(value);
|
||||
// Find custom preset and switch to it
|
||||
PRESETS.values().stream()
|
||||
.filter(ConfigPreset::isCustom)
|
||||
.findFirst()
|
||||
.ifPresent(p -> activePresetId = p.id);
|
||||
}
|
||||
|
||||
// ── Save / Load ───────────────────────────────────────────────────────────
|
||||
|
||||
public static void save() {
|
||||
JsonObject root = new JsonObject();
|
||||
root.addProperty("preset", activePresetId);
|
||||
JsonObject values = new JsonObject();
|
||||
SETTINGS.forEach((id, entry) -> values.addProperty(id, entry.get()));
|
||||
root.add("values", values);
|
||||
try (Writer w = Files.newBufferedWriter(CONFIG_PATH)) {
|
||||
GSON.toJson(root, w);
|
||||
} catch (IOException e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
if (!Files.exists(CONFIG_PATH)) { save(); return; }
|
||||
try (Reader r = Files.newBufferedReader(CONFIG_PATH)) {
|
||||
JsonObject root = GSON.fromJson(r, JsonObject.class);
|
||||
if (root == null) return;
|
||||
if (root.has("preset")) activePresetId = root.get("preset").getAsString();
|
||||
if (root.has("values")) {
|
||||
JsonObject values = root.getAsJsonObject("values");
|
||||
SETTINGS.forEach((id, entry) -> {
|
||||
if (values.has(id)) entry.set(values.get(id).getAsBoolean());
|
||||
});
|
||||
}
|
||||
} catch (IOException e) { e.printStackTrace(); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||
|
||||
public class ModMenuIntegration implements ModMenuApi {
|
||||
@Override
|
||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||
return ConfigScreen::new;
|
||||
}
|
||||
}
|
||||
40
src/client/java/dev/tggamesyt/szar/client/ModSettings.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ModSettings {
|
||||
// ── Declare setting references for easy typed access ──────────────────────
|
||||
public static ConfigEntry RACIST;
|
||||
public static ConfigEntry GAMBLING;
|
||||
public static ConfigEntry NSFW;
|
||||
// To add a new setting: just add a line here and in init() below. That's it.
|
||||
|
||||
public static void init() {
|
||||
// newSetting(id, displayName, defaultValue)
|
||||
// newSetting(id, displayName, defaultValue, "resourcepack/id")
|
||||
RACIST = ModConfig.newSetting("racist", "Block Racist content", true, "szar:racist");
|
||||
GAMBLING = ModConfig.newSetting("gambling", "Block Gambling", true);
|
||||
NSFW = ModConfig.newSetting("nsfw", "Block NSFW content",true, "szar:nsfw");
|
||||
|
||||
// ── Presets ───────────────────────────────────────────────────────────
|
||||
// newPreset(id, displayName, Map<settingId, value>)
|
||||
// Pass null map for the "custom" preset (user-editable, no fixed values)
|
||||
|
||||
ModConfig.newPreset("none", "18+", Map.of(
|
||||
"racist", false,
|
||||
"gambling", false,
|
||||
"nsfw", false
|
||||
));
|
||||
ModConfig.newPreset("some", "17+", Map.of(
|
||||
"racist", false,
|
||||
"gambling", false,
|
||||
"nsfw", true
|
||||
));
|
||||
ModConfig.newPreset("all", "Minor", Map.of(
|
||||
"racist", true,
|
||||
"gambling", true,
|
||||
"nsfw", true
|
||||
));
|
||||
ModConfig.newPreset("custom", "Custom", null); // null = custom, toggles stay editable
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package dev.tggamesyt.szar.client;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.resource.ResourcePackManager;
|
||||
import net.minecraft.resource.ResourcePackProfile;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ResourcePackHelper {
|
||||
|
||||
public static void applyAll(MinecraftClient client) {
|
||||
ResourcePackManager manager = client.getResourcePackManager();
|
||||
manager.scanPacks();
|
||||
|
||||
Set<String> original = new HashSet<>(
|
||||
manager.getEnabledProfiles().stream()
|
||||
.map(p -> p.getName())
|
||||
.toList()
|
||||
);
|
||||
|
||||
Set<String> enabledNames = new HashSet<>(
|
||||
manager.getEnabledProfiles().stream()
|
||||
.map(p -> p.getName())
|
||||
.toList()
|
||||
);
|
||||
|
||||
for (ConfigEntry entry : ModConfig.allSettings()) {
|
||||
if (!entry.hasResourcePack()) continue;
|
||||
if (entry.get()) {
|
||||
enabledNames.add(entry.linkedResourcePack);
|
||||
} else {
|
||||
enabledNames.remove(entry.linkedResourcePack);
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledNames.equals(original)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Use the manager to set enabled packs properly — this is the key fix
|
||||
manager.setEnabledProfiles(enabledNames);
|
||||
|
||||
// Sync back to options and save
|
||||
client.options.resourcePacks.clear();
|
||||
client.options.resourcePacks.addAll(
|
||||
manager.getEnabledProfiles().stream()
|
||||
.map(p -> p.getName())
|
||||
.toList()
|
||||
);
|
||||
client.options.write();
|
||||
client.reloadResources();
|
||||
}
|
||||
|
||||
public static Set<String> getManagedPacks() {
|
||||
Set<String> managed = new HashSet<>();
|
||||
for (ConfigEntry entry : ModConfig.allSettings()) {
|
||||
if (entry.hasResourcePack()) managed.add(entry.linkedResourcePack);
|
||||
}
|
||||
return managed;
|
||||
}
|
||||
|
||||
public static boolean isManaged(String packName) {
|
||||
return getManagedPacks().contains(packName);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
|
||||
@@ -16,6 +17,9 @@ import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
|
||||
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreens;
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
@@ -43,6 +47,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.Box;
|
||||
@@ -91,6 +96,34 @@ public class SzarClient implements ClientModInitializer {
|
||||
int loopStart = startOffset + startLength;
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
||||
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);
|
||||
});
|
||||
ModSettings.init(); // register all settings & presets FIRST
|
||||
ModConfig.load(); // then load saved values
|
||||
|
||||
ResourceManagerHelper.registerBuiltinResourcePack(
|
||||
new Identifier(MOD_ID, "nsfw"),
|
||||
FabricLoader.getInstance().getModContainer(MOD_ID).get(),
|
||||
Text.literal("NSFW Censorship"),
|
||||
ResourcePackActivationType.NORMAL
|
||||
);
|
||||
ResourceManagerHelper.registerBuiltinResourcePack(
|
||||
new Identifier(MOD_ID, "racist"),
|
||||
FabricLoader.getInstance().getModContainer(MOD_ID).get(),
|
||||
Text.literal("Racism Censorship"),
|
||||
ResourcePackActivationType.NORMAL
|
||||
);
|
||||
EntityRendererRegistry.register(Szar.RADIATION_AREA, EmptyEntityRenderer::new);
|
||||
ClientPlayNetworking.registerGlobalReceiver(Szar.PLAY_VIDEO,
|
||||
(client, handler, buf, responseSender) -> {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package dev.tggamesyt.szar.client.mixin;
|
||||
|
||||
import dev.tggamesyt.szar.client.ResourcePackHelper;
|
||||
import net.minecraft.client.gui.screen.pack.ResourcePackOrganizer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ResourcePackOrganizer.Pack.class)
|
||||
public interface PackMixin {
|
||||
|
||||
@Shadow
|
||||
String getName();
|
||||
|
||||
@Inject(method = "canBeEnabled()Z", at = @At("RETURN"), cancellable = true)
|
||||
private void onCanBeEnabled(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (ResourcePackHelper.isManaged(this.getName())) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "canBeDisabled()Z", at = @At("RETURN"), cancellable = true)
|
||||
private void onCanBeDisabled(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (ResourcePackHelper.isManaged(this.getName())) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.tggamesyt.szar.client.mixin;
|
||||
|
||||
import dev.tggamesyt.szar.client.ResourcePackHelper;
|
||||
import net.minecraft.client.gui.screen.pack.PackScreen;
|
||||
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(PackScreen.class)
|
||||
public class PackScreenCloseMixin {
|
||||
|
||||
@Inject(method = "close", at = @At("HEAD"))
|
||||
private void onClose(CallbackInfo ci) {
|
||||
ResourcePackHelper.applyAll(net.minecraft.client.MinecraftClient.getInstance());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
"HeldItemRendererMixin",
|
||||
"ItemRendererMixin",
|
||||
"MouseMixin",
|
||||
"PackMixin",
|
||||
"PackScreenCloseMixin",
|
||||
"PlayerEntityRendererMixin",
|
||||
"PlayerHeldItemFeatureRendererMixin",
|
||||
"PlayerModelMixin",
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.particle.BlockStateParticleEffect;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
@@ -130,6 +131,7 @@ public class FaszItem extends BlockItem {
|
||||
|
||||
// If the entity is a player → apply special effect logic
|
||||
if (living instanceof PlayerEntity target) {
|
||||
if (PlayerConfigStore.get(target, "nsfw")) { return;}
|
||||
int chance = 5; // 1/5 default
|
||||
ItemStack offhand = user.getOffHandStack();
|
||||
if (!offhand.isEmpty() && offhand.isOf(CNDM.getItem())) {
|
||||
|
||||
41
src/main/java/dev/tggamesyt/szar/PlayerConfigStore.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package dev.tggamesyt.szar;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import java.util.*;
|
||||
|
||||
public class PlayerConfigStore {
|
||||
|
||||
// Map of player UUID → (setting id → value)
|
||||
private static final Map<UUID, Map<String, Boolean>> store = new HashMap<>();
|
||||
|
||||
public static void set(ServerPlayerEntity player, Map<String, Boolean> config) {
|
||||
store.put(player.getUuid(), config);
|
||||
}
|
||||
|
||||
public static boolean get(ServerPlayerEntity player, String settingId) {
|
||||
Map<String, Boolean> config = store.get(player.getUuid());
|
||||
if (config == null) return false; // default if not synced yet
|
||||
return config.getOrDefault(settingId, false);
|
||||
}
|
||||
|
||||
public static boolean get(PlayerEntity player, String settingId) {
|
||||
Map<String, Boolean> config = store.get(player.getUuid());
|
||||
if (config == null) return false; // default if not synced yet
|
||||
return config.getOrDefault(settingId, false);
|
||||
}
|
||||
|
||||
public static boolean get(UUID uuid, String settingId) {
|
||||
Map<String, Boolean> config = store.get(uuid);
|
||||
if (config == null) return false;
|
||||
return config.getOrDefault(settingId, false);
|
||||
}
|
||||
|
||||
public static void remove(ServerPlayerEntity player) {
|
||||
store.remove(player.getUuid());
|
||||
}
|
||||
|
||||
public static boolean hasSynced(ServerPlayerEntity player) {
|
||||
return store.containsKey(player.getUuid());
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class RouletteBlock extends Block implements BlockEntityProvider {
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos,
|
||||
PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
|
||||
if (PlayerConfigStore.get(player, "gambling")) {return ActionResult.FAIL;}
|
||||
if (hand != Hand.MAIN_HAND) return ActionResult.PASS;
|
||||
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
|
||||
@@ -92,7 +92,7 @@ public class SlotMachineBlock extends Block implements BlockEntityProvider {
|
||||
@Override
|
||||
public ActionResult onUse(BlockState state, World world, BlockPos pos,
|
||||
PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||
|
||||
if (PlayerConfigStore.get(player, "gambling")) {return ActionResult.FAIL;}
|
||||
if (hand != Hand.MAIN_HAND) return ActionResult.PASS;
|
||||
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
|
||||
@@ -133,13 +133,15 @@ public class Szar implements ModInitializer {
|
||||
SoundEvent.of(new Identifier(Szar.MOD_ID, "won"))
|
||||
);
|
||||
public static final SoundEvent MERL_SOUND =
|
||||
SoundEvent.of(new Identifier("szar", "merl"));
|
||||
SoundEvent.of(new Identifier(MOD_ID, "merl"));
|
||||
public static final Identifier PLANE_ANIM_PACKET =
|
||||
new Identifier(MOD_ID, "plane_anim");
|
||||
public static final Identifier NAZI_HAND_GESTURE = new Identifier("szar", "hit_hand");
|
||||
public static final Identifier NAZI_HAND_GESTURE = new Identifier(MOD_ID, "hit_hand");
|
||||
public static final Identifier OPEN_URL = new Identifier(MOD_ID, "epsteinfiles");
|
||||
public static final Identifier PLAY_VIDEO =
|
||||
new Identifier(MOD_ID, "play_video");
|
||||
public static final Identifier CONFIG_SYNC = new Identifier(MOD_ID, "config_sync");
|
||||
|
||||
|
||||
public static final Block SZAR_BLOCK =
|
||||
new SzarBlock();
|
||||
@@ -296,7 +298,7 @@ public class Szar implements ModInitializer {
|
||||
new Identifier(MOD_ID, "szar_group"),
|
||||
FabricItemGroup.builder()
|
||||
.displayName(Text.translatable("itemgroup.szar_group"))
|
||||
.icon(() -> new ItemStack(Szar.CIGANYBLOCK)) // icon item
|
||||
.icon(() -> new ItemStack(Szar.CANNABIS_ITEM)) // icon item
|
||||
.entries((displayContext, entries) -> {
|
||||
// drugs
|
||||
entries.add(Szar.CANNABIS_ITEM);
|
||||
@@ -360,6 +362,27 @@ public class Szar implements ModInitializer {
|
||||
private final Map<UUID, BlockPos> sleepingPlayers = new HashMap<>();
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
ServerPlayNetworking.registerGlobalReceiver(CONFIG_SYNC,
|
||||
(server, player, handler, buf, responseSender) -> {
|
||||
// Read on netty thread, process on server thread
|
||||
int count = buf.readInt();
|
||||
Map<String, Boolean> config = new HashMap<>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String id = buf.readString();
|
||||
boolean value = buf.readBoolean();
|
||||
config.put(id, value);
|
||||
}
|
||||
|
||||
// Always handle game state on the server thread
|
||||
server.execute(() -> {
|
||||
PlayerConfigStore.set(player, config);
|
||||
});
|
||||
});
|
||||
|
||||
// Clean up when player leaves
|
||||
ServerPlayConnectionEvents.DISCONNECT.register(
|
||||
(handler, server) -> PlayerConfigStore.remove(handler.player)
|
||||
);
|
||||
PlayerMovementManager.init();
|
||||
ServerCosmetics.init();
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
@@ -1571,6 +1594,7 @@ public class Szar implements ModInitializer {
|
||||
}
|
||||
|
||||
private void givePregnantEffect(ServerPlayerEntity player, ServerPlayerEntity partner, int chance) {
|
||||
if (PlayerConfigStore.get(player, "nsfw") || PlayerConfigStore.get(partner, "nsfw")) { return; }
|
||||
if (partner.getOffHandStack().getItem() == Szar.CNDM) {
|
||||
partner.getOffHandStack().decrement(1);
|
||||
partner.dropStack(new ItemStack(WHITE_LIQUID));
|
||||
|
||||
|
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 94 KiB |
@@ -88,5 +88,29 @@
|
||||
"item.szar.hello.desc": "Alex Savage - OMFG - Hello (Dark Remix)",
|
||||
|
||||
"death.attack.plane_crash": "%1$s crashed their plane",
|
||||
"death.attack.plane_crash.player": "%1$s was killed when %2$s crashed their plane"
|
||||
"death.attack.plane_crash.player": "%1$s was killed when %2$s crashed their plane",
|
||||
|
||||
"painting.szar.nyansniffer.title": "Nyan Sniffer",
|
||||
"painting.szar.nyansniffer.author": "Unknown (Szar Mod)",
|
||||
|
||||
"painting.szar.matrix.title": "Matrix",
|
||||
"painting.szar.matrix.author": "Unknown (Szar Mod)",
|
||||
|
||||
"painting.szar.frogs.title": "Frogs",
|
||||
"painting.szar.frogs.author": "Minecraft Live (Szar Mod)",
|
||||
|
||||
"painting.szar.bounce.title": "Bounce",
|
||||
"painting.szar.bounce.author": "Unknown (Szar Mod)",
|
||||
|
||||
"painting.szar.block_wave.title": "Block Wave",
|
||||
"painting.szar.block_wave.author": "Unknown (Szar Mod)",
|
||||
|
||||
"painting.szar.bloc.title": "Bloc",
|
||||
"painting.szar.bloc.author": "Unknown (Szar Mod)",
|
||||
|
||||
"painting.szar.axolotl.title": "Axolotl",
|
||||
"painting.szar.axolotl.author": "Unknown (Szar Mod)",
|
||||
|
||||
"painting.szar.chicken_jokey.title": "Chicken Jokey",
|
||||
"painting.szar.chicken_jokey.author": "Unknown (Szar Mod)"
|
||||
}
|
||||
|
||||
BIN
src/main/resources/assets/szar/szarmod.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
src/main/resources/assets/szar/textures/block/questionmark.png
Normal file
|
After Width: | Height: | Size: 650 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
src/main/resources/assets/szar/textures/item/questionmark.png
Normal file
|
After Width: | Height: | Size: 650 B |
BIN
src/main/resources/assets/szar/textures/questionmark.png
Normal file
|
After Width: | Height: | Size: 650 B |
@@ -19,6 +19,9 @@
|
||||
],
|
||||
"main": [
|
||||
"dev.tggamesyt.szar.Szar"
|
||||
],
|
||||
"modmenu": [
|
||||
"dev.tggamesyt.szar.client.ModMenuIntegration"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
@@ -32,5 +35,9 @@
|
||||
"fabricloader": ">=${loader_version}",
|
||||
"fabric": "*",
|
||||
"minecraft": "${minecraft_version}"
|
||||
},
|
||||
"suggests": {
|
||||
"modmenu": "*",
|
||||
"cloth-config": "*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"block.szar.fasz": "?",
|
||||
"item.szar.epstein_files": "?",
|
||||
"item.szar.cndm": "?",
|
||||
"death.attack.fck": "%1$s was killed by %2$s",
|
||||
"item.szar.white_liquid": "?"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "szar:block/questionmark"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/questionmark"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/questionmark"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/questionmark"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/questionmark"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/questionmark"
|
||||
}
|
||||
}
|
||||
6
src/main/resources/resourcepacks/nsfw/pack.mcmeta
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"pack_format": 15,
|
||||
"description": "Szar built-in resource pack"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"block.szar.cigany": "? Block",
|
||||
"item.szar.nwordpass": "?",
|
||||
"entity.szar.nigger": "Monkey",
|
||||
"item.szar.nigger_spawn_egg":"Monkey Spawn Egg",
|
||||
"item.szar.gypsy_spawn_egg":"Burglar Spawn Egg",
|
||||
|
||||
"item.szar.niggerite_ingot": "Monkey Ingot",
|
||||
"block.szar.niggerite_block": "Monkey Block",
|
||||
"item.szar.niggerite_sword": "Monkey Sword",
|
||||
"item.szar.niggerite_axe": "Monkey Axe",
|
||||
"item.szar.niggerite_pickaxe": "Monkey Pickaxe",
|
||||
"item.szar.niggerite_shovel": "Monkey Shovel",
|
||||
"item.szar.niggerite_hoe": "Monkey Hoe",
|
||||
"item.szar.niggerite_chestplate": "Monkey Chestplate",
|
||||
"item.szar.niggerite_leggings": "Monkey Leggings",
|
||||
"item.szar.niggerite_boots": "Monkey Boots",
|
||||
"item.szar.niggerite_helmet": "Monkey Helmet",
|
||||
"entity.szar.islam_terrorist": "Creeper Player",
|
||||
"item.szar.terrorist_spawn_egg": "Creeper Player Spawn Egg",
|
||||
"entity.szar.gypsy": "Burglar",
|
||||
"item.szar.epstein_files": "?",
|
||||
"entity.szar.epstein": "Old Man",
|
||||
"item.szar.epstein_spawn_egg": "Old Man Spawn Egg"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "szar:block/questionmark"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/questionmark"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "szar:item/questionmark"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 550 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
6
src/main/resources/resourcepacks/racist/pack.mcmeta
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"pack_format": 15,
|
||||
"description": "Szar built-in resource pack"
|
||||
}
|
||||
}
|
||||