35 Commits
v4.0.0 ... main

Author SHA1 Message Date
Martin Prokoph
f583f515f4 Finalize v6.0.0 2025-01-26 19:34:08 +01:00
Martin Prokoph
8b920a4b1a fix: also apply PR #81 to slider widgets 2025-01-26 19:28:20 +01:00
Martin Prokoph
3406380d90 Merge pull request #77 from yichifauzi/main
Add Traditional Chinese (zh_tw.json)
2025-01-26 19:23:55 +01:00
Martin Prokoph
f78ba317a8 Merge pull request #81 from fzzyhmstrs/main
Remove IconicButtons init
2025-01-26 19:23:43 +01:00
Martin Prokoph
4c78e266fd Merge pull request #88 from TeamMidnightDust/dev
VisualOverhaul 6.0.0 for 1.21.4
2025-01-26 19:23:29 +01:00
Martin Prokoph
18d1f5af76 feat: get colored water buckets working again 2025-01-26 18:18:10 +01:00
Martin Prokoph
132d05a1d2 fix: building 2025-01-26 14:52:33 +01:00
Martin Prokoph
1ae9580315 feat: fake block models
- Instead of registering a block for the jukebox top, we can now render models without a block being registered at all
- This opens up a lot of interesting new visuals in the near future :)
2025-01-26 14:29:21 +01:00
Martin Prokoph
9dd620515c feat: improve disc recognition
- Will now display textures according to the stack's specified model/custom modeldata
This allows most custom disc datapacks to work :)
2025-01-26 14:13:23 +01:00
Martin Prokoph
821d5bd87c clean: remove leftovers on neoforge 2025-01-26 01:47:00 +01:00
Martin Prokoph
d95a18b28b feat: rework dynamic item colors 2025-01-26 01:46:16 +01:00
Martin Prokoph
3307ba337e fix: darkening of disabled buttons 2025-01-26 01:13:00 +01:00
Martin Prokoph
0a905a79d1 feat: dynamic round disc model generation
- Cursed, but it works :)
2025-01-26 00:55:03 +01:00
Martin Prokoph
16f558644c port: 1.21.4
- Also substantially improve iconic buttons
2025-01-26 00:53:51 +01:00
dirtTW
7f1aaa3113 Apply suggestions from code review
Co-authored-by: notlin4 <121224522+notlin4@users.noreply.github.com>
2024-10-01 21:55:49 +07:00
fzzyhmstrs
27be58d6de Remove IconicButtons init
removes the init method call that is leaking `this` from iconic$onInitButton
2024-09-21 11:47:49 -04:00
dirtTW
80af118f78 Add Traditional Chinese (zh_tw.json)
Add Traditional Chinese localization
2024-08-09 00:50:58 +07:00
Martin Prokoph
51c354c533 Remove debug log spam & fix crashes
- Remove debug messages when receiving packets
- Fix dedicated server crashes on Fabric and Neoforge
2024-06-19 13:21:22 +02:00
Martin Prokoph
cd9db8c8bc Port to 1.21
- Rewrite packet system to use vanilla payloads
- Water bottles will now appear slightly transparent
- One of the hardest 1.21 ports yet
2024-06-18 19:06:41 +02:00
Martin Prokoph
f1d4e36ed9 Merge pull request #66 from TheLegendofSaram/main
Mexican Spanish translation
2024-06-17 15:20:44 +02:00
Santiago Hernandez
5237106a48 Mexican Spanish translation
A small translation for the mod
2024-04-15 22:38:07 -04:00
Martin Prokoph
680d2a3a8b VisualOverhaul 5.1.0 - Code overhaul!
- Update to 1.20.4
- Switch Forge version to NeoForge
- Update resourcepacks & add round relic disc (thanks to @SuperNoobYT)
- Furnaces will now show results when finished (closes #61)
- Fix crash related to sound events (closes #60, #52)
- Fix crash related to button icons (closes #59, #55, #54, likely #49)
- Fix log spam when mod is only present on server (closes #33)
- Fix jukeboxes staying powered after playback has finished (closes #53)
2024-02-23 21:10:02 +01:00
Martin Prokoph
ca9b7a0357 Merge pull request #44 from SuperNoobYT/main
Fixing the new music disc "relic" not being supported by the rounddiscs option
2024-02-23 16:20:44 +01:00
Supernoob
65a3cfbc5d Updated ressources pack to 1.20
Updated mcmeta
Added Relic disc to round discs
2023-06-26 00:34:01 +02:00
Motschen
e9539ba28f VisualOverhaul 5.0.1 - Port to 1.20
- Update to 1.20
- Fix #41 & #40
2023-06-11 13:15:10 +02:00
Motschen
c6ccdb0d95 VisualOverhaul 5.0.0 - The Iconic Update
- Port to 1.19.4
- Use Architectury -> Forge & native Quilt support!
- New Feature: Icon Buttons!
  - Makes buttons look less bland by adding icons to them
  - Loaded from resourcepacks
  - Currently uses vanilla items as icons
- Organize config screen in tabs
2023-04-26 20:47:43 +02:00
Martin Prokoph
363a9ab634 Merge pull request #34 from Calvineries/patch-1
Create fr_fr.json
2023-04-26 20:29:28 +02:00
Calvineries
801d46d9d2 Create fr_fr.json 2023-01-21 10:21:22 +01:00
Motschen
08324fbfb6 Disable Phonos compat until I can fix remap issues 2022-11-30 16:03:18 +01:00
Motschen
94c6929099 Try to make Phonos compat work again
For some reason, the Phonos compat classes aren't getting remapped correctly, causing a crash.
2022-11-20 18:55:17 +01:00
Motschen
2eb56f0d95 Compress images 2022-11-19 16:37:18 +01:00
Motschen
478bad8d38 Add correct icon for Forge 2022-11-19 16:23:08 +01:00
Motschen
258cc3c64e Port to Architectury 2022-11-19 16:18:28 +01:00
Motschen
7fb093de15 VisualOverhaul 4.1.1 - Update to 1.19 2022-06-18 11:35:05 +02:00
Motschen
37e5789081 VisualOverhaul 4.1.0 - 1.18.2, colored lilypads and improvements
Fix #29
Fix #27
Fix #26
Fix #25
Fix #24
2022-03-10 20:59:02 +01:00
292 changed files with 3048 additions and 2188 deletions

33
.gitignore vendored Executable file → Normal file
View File

@@ -1,25 +1,20 @@
# gradle
.gradle/
out/
classes/
build/
# idea
.idea/
*.iml
*.ipr
run/
*.iws
# vscode
.settings/
.vscode/
out/
*.iml
.gradle/
output/
bin/
libs/
.architectury-transformer/
.classpath
.project
# fabric
run/
.idea/
classes/
.metadata
.vscode
.settings
*.launch

135
build.gradle Executable file → Normal file
View File

@@ -1,86 +1,75 @@
plugins {
id 'fabric-loom' version '0.10-SNAPSHOT'
id 'maven-publish'
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
minecraft {
architectury {
minecraft = rootProject.minecraft_version
}
repositories {
maven { url "https://jitpack.io" }
maven { url "https://api.modrinth.com/maven" }
maven {
url = "https://api.modrinth.com/maven"
}
}
dependencies {
//to change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
subprojects {
apply plugin: 'dev.architectury.loom'
apply plugin: 'architectury-plugin'
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
include "maven.modrinth:midnightlib:${project.midnightlib_version}"
dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
// The following line declares the mojmap mappings, you may use other mappings as well
//mappings loom.officialMojangMappings()
// The following line declares the yarn mappings you may select this one as well.
mappings loom.layered {
it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2")
it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version")
}
}
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile).configureEach {
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
// If Javadoc is generated, this must be specified in that task too.
it.options.encoding = "UTF-8"
// Minecraft 1.17 (21w19a) upwards uses Java 16.
it.options.release = 16
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"}
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
allprojects {
apply plugin: "java"
apply plugin: "architectury-plugin"
apply plugin: "maven-publish"
archivesBaseName = rootProject.archives_base_name
version = rootProject.mod_version
group = rootProject.maven_group
repositories {
// 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.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
options.release = 21
}
ext {
releaseChangelog = {
def changes = new StringBuilder()
changes << "## VisualOverhaul v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/VisualOverhaul/commits/)"
def proc = "git log --max-count=1 --pretty=format:%s".execute()
proc.in.eachLine { line ->
def processedLine = line.toString()
if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) {
changes << "\n- ${processedLine.capitalize()}"
}
}
proc.waitFor()
return changes.toString()
}
}
java {
withSourcesJar()
}
}

19
common/build.gradle Normal file
View File

@@ -0,0 +1,19 @@
architectury {
common(rootProject.enabled_platforms.split(","))
}
loom {
}
repositories {
maven { url "https://api.modrinth.com/maven" }
}
dependencies {
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
// Do NOT use other classes from fabric loader
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
modCompileOnlyApi "maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric"
// Remove the next line if you don't want to depend on the API
//modApi "dev.architectury:architectury:${rootProject.architectury_version}"
}

View File

@@ -0,0 +1,69 @@
package eu.midnightdust.visualoverhaul;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.model.ModelNameSupplier;
import net.minecraft.client.model.SpriteGetter;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.model.*;
import net.minecraft.client.render.model.json.JsonUnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.LOGGER;
public class FakeBlocks {
private static final Baker BAKER = new FakeBaker();
private static final Map<Identifier, BakedModel> FAKE_MODELS = new HashMap<>();
private static final BlockRenderManager renderManager = MinecraftClient.getInstance().getBlockRenderManager();
public static void reload(ResourceManager manager) {
manager.findResources("models", path -> path.getPath().startsWith("models/fakeblock") && path.getPath().endsWith(".json")).forEach((id, resource) -> {
try {
JsonUnbakedModel unbaked = JsonUnbakedModel.deserialize(resource.getReader());
BakedModel baked = unbaked.bake(new ModelTextures.Builder().addFirst(unbaked.getTextures()).build(() -> "#fakeblock"), BAKER,
new ModelBakeSettings(){}, Boolean.TRUE.equals(unbaked.getAmbientOcclusion()), unbaked.getGuiLight() != null && unbaked.getGuiLight().isSide(), unbaked.getTransformation());
Identifier fakeId = Identifier.of(id.getNamespace(), id.getPath().replace("models/fakeblock/", "").replace(".json", ""));
FAKE_MODELS.put(fakeId, baked);
if (VOConfig.debug) LOGGER.info("Successfully loaded fake block model: {}", fakeId);
} catch (IOException e) {
LOGGER.error("Error occurred while loading fake block model {}", id.toString(), e);
}
});
}
public static void renderFakeBlock(Identifier id, BlockPos pos, BlockRenderView world, MatrixStack matrices, VertexConsumer vertexConsumer) {
renderManager.getModelRenderer().render(world, FAKE_MODELS.get(id), Blocks.DIRT.getDefaultState(), // State is just needed for a few generic checks
pos, matrices, vertexConsumer, false, Random.create(), 0, OverlayTexture.DEFAULT_UV);
}
public static class FakeBaker implements Baker {
public BakedModel bake(Identifier id, ModelBakeSettings settings) {
return null; // Not used in Json models, so we just leave ít like this and cross our fingers.
}
@Override
public SpriteGetter getSpriteGetter() {
return new SpriteGetter() {
static final SpriteIdentifier MISSING = new SpriteIdentifier(Identifier.ofVanilla("textures/atlas/blocks.png"), Identifier.ofVanilla("missingno"));
@Override public Sprite get(SpriteIdentifier spriteId) { return spriteId.getSprite(); }
@Override public Sprite getMissing(String textureId) { return MISSING.getSprite(); }
};
}
public ModelNameSupplier getModelNameSupplier() { return () -> "#fakeblock"; }
}
}

View File

@@ -0,0 +1,134 @@
package eu.midnightdust.visualoverhaul;
import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import eu.midnightdust.visualoverhaul.mixin.TextureManagerAccessor;
import eu.midnightdust.visualoverhaul.util.ModIconUtil;
import eu.midnightdust.visualoverhaul.util.VOColorUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.texture.NativeImageBackedTexture;
import net.minecraft.client.texture.ResourceTexture;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.resource.ResourceManager;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableTextContent;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper;
import net.minecraft.util.math.MathHelper;
import org.apache.logging.log4j.LogManager;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.LOGGER;
import static eu.midnightdust.visualoverhaul.util.VOColorUtil.alphaAndBrightness;
public class IconicButtons {
MinecraftClient client = MinecraftClient.getInstance();
TextureManager textureManager = client.getTextureManager();
private String buttonId;
private Text prevText;
private Identifier iconId;
private static final Map<Identifier, Identifier> ICONS = new HashMap<>();
public IconicButtons() {}
public void init(ClickableWidget widget) {
if (widget == null || widget.getMessage() == null || widget.getMessage().getContent() == null) return;
prevText = widget.getMessage();
buttonId = (widget.getMessage().getContent() instanceof TranslatableTextContent translatableTextContent) ? translatableTextContent.getKey().toLowerCase() : "";
if (VOConfig.buttonIcons && !buttonId.isEmpty()) {
if (VOConfig.debug) System.out.println(buttonId);
iconId = Identifier.tryParse("iconic:textures/gui/icons/" + buttonId.toLowerCase()+".png");
// Show mod icons in MidnightConfig overview
if (buttonId.endsWith(".midnightconfig.title")) {
iconId = Identifier.of("modid", buttonId.replace(".midnightconfig.title", "") + "_icon");
NativeImageBackedTexture icon = new ModIconUtil(buttonId.replace(".midnightconfig.title", "")).createModIcon();
if (icon != null) {
client.getTextureManager().registerTexture(iconId, icon);
ICONS.put(iconId, iconId);
} else {
iconId = null;
}
}
// Handle dynamic icons
else if (iconId != null && !ICONS.containsKey(iconId)) {
if (((TextureManagerAccessor)textureManager).getResourceContainer().getResource(iconId).isEmpty())
return; // If no icon is present, don't load it
ResourceTexture abstractTexture = new ResourceTexture(iconId);
if (VOConfig.debug) System.out.println("Loading dynamic icon: "+iconId);
try {
abstractTexture.loadContents(((TextureManagerAccessor)textureManager).getResourceContainer());
} catch (Exception e) {e.fillInStackTrace();}
textureManager.registerTexture(iconId, abstractTexture);
ICONS.put(iconId, iconId);
}
}
}
public void renderIcons(DrawContext context, ClickableWidget widget, float alpha) {
if (widget.getMessage() == null || widget.getWidth() <= 20) return;
if (prevText != widget.getMessage()) init(widget);
if (VOConfig.buttonIcons && !buttonId.isEmpty() && iconId != null && ICONS.containsKey(iconId)) {
int scaledWidth = client.getWindow().getScaledWidth();
boolean limitedSpace = client.textRenderer.getWidth(widget.getMessage()) > (widget.getWidth() * 0.75f);
boolean showLeftWhenBoth = (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.BOTH) && !limitedSpace) || (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.BOTH) && widget.getX() < scaledWidth/2);
boolean showRightWhenBoth = (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.BOTH) && !limitedSpace) || (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.BOTH) && widget.getX() > scaledWidth/2);
int color = widget.active ? alphaAndBrightness(alpha, 1.0F) : alphaAndBrightness(alpha, 0.3F);
RenderSystem.enableBlend();
RenderSystem.enableDepthTest();
int inset = 2;
if (VOConfig.zoomIconOnHover && widget.isSelected() && widget.active) inset = 1;
int size = 20-inset*2;
Identifier textureId = ICONS.get(iconId);
if (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.LEFT) || showLeftWhenBoth || (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.LOCATION) && widget.getX() < scaledWidth/2))
context.drawTexture(RenderLayer::getGuiTextured, textureId, widget.getX()+inset, widget.getY()+inset, 0, 0, size, size, size, size, size, size, color);
if (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.RIGHT) || showRightWhenBoth || (VOConfig.buttonIconPosition.equals(VOConfig.IconPosition.LOCATION) && widget.getX()+widget.getWidth() > scaledWidth/2))
context.drawTexture(RenderLayer::getGuiTextured, textureId, widget.getX()+widget.getWidth()-20+inset, widget.getY()+inset, 0, 0, size, size, size, size, size, size, color);
RenderSystem.disableBlend();
RenderSystem.disableDepthTest();
}
}
public static void reload(ResourceManager manager) {
manager.findResources("textures", path -> path.getNamespace().equals("iconic") && path.getPath().contains(".properties")).forEach((id, resource) -> {
if (manager.getResource(id).isEmpty()) return;
try (InputStream stream = manager.getResource(id).get().getInputStream()) {
Identifier iconId = Identifier.of(id.getNamespace(), id.getPath().replace(".properties", ".png"));
if (manager.getResource(iconId).isPresent()) return;
Properties properties = new Properties();
properties.load(stream);
while (properties.get("properties") != null) {
Identifier propertiesId = Identifier.of(properties.getProperty("properties"));
String textureId = propertiesId.toString().replace(".properties", ".png");
properties.clear();
if (manager.getResource(Identifier.tryParse(textureId)).isPresent()) { // If a texture is present at the location of the referenced properties file, use that instead
properties.put("texture", textureId);
}
else if (manager.getResource(propertiesId).isPresent()) {
properties.load(manager.getResource(propertiesId).get().getInputStream()); // Else load the referenced properties file, if present
} else return;
}
if (properties.get("texture") != null) {
Identifier textureId = Identifier.tryParse(properties.getProperty("texture"));
ICONS.put(iconId, textureId);
}
} catch (Exception e) {
LOGGER.error("Error occurred while loading texture.properties for button icon {}", id.toString(), e);
}
});
}
}

View File

@@ -0,0 +1,16 @@
package eu.midnightdust.visualoverhaul;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.MOD_ID;
public class VisualOverhaulClient {
public static int waterColor = 4159204;
public static int foliageColor = -8934609;
public static int grassColor = -8934609;
public static int potionColor = -13083194;
public static void onInitializeClient() {
VOConfig.init(MOD_ID, VOConfig.class);
}
}

View File

@@ -0,0 +1,31 @@
package eu.midnightdust.visualoverhaul;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class VisualOverhaulCommon {
public static final String MOD_ID = "visualoverhaul";
public static final Logger LOGGER = LoggerFactory.getLogger("VisualOverhaul");
public static final List<UUID> playersWithMod = new ArrayList<>();
public static final Map<BlockPos, ItemStack> jukeboxItems = new HashMap<>();
public static final Identifier HELLO_PACKET = id("hello");
public static final Identifier UPDATE_ITEMS_PACKET = id("update_items");
public static final Identifier UPDATE_TYPE_POTION_BOTTLES = id("type_brewingstand");
public static final Identifier UPDATE_TYPE_RECORD = id("type_record");
public static final Identifier UPDATE_TYPE_FURNACE_ITEMS = id("type_furnace");
public static Identifier id(String path) {
return Identifier.of(MOD_ID, path);
}
}

View File

@@ -5,14 +5,15 @@ import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.entity.model.EntityModelLayer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.id;
public class FurnaceWoodenPlanksModel extends Model {
private static ModelPart bb_main;
public static final EntityModelLayer WOODEN_PLANKS_MODEL_LAYER = new EntityModelLayer(new Identifier("visualoverhaul", "wooden_planks"), "main");
public static final EntityModelLayer WOODEN_PLANKS_MODEL_LAYER = new EntityModelLayer(id("wooden_planks"), "main");
public FurnaceWoodenPlanksModel(ModelPart root) {
super(RenderLayer::getEntitySolid);
super(root, RenderLayer::getEntitySolid);
bb_main = root;
bb_main.setPivot(0.0F, 24.0F, 0.0F);
}
@@ -33,7 +34,7 @@ public class FurnaceWoodenPlanksModel extends Model {
return modelData;
}
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
bb_main.render(matrices, vertices, light, overlay, red, green, blue, alpha);
}
// public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, int color) {
// bb_main.render(matrices, vertices, light, overlay);
// }
}

View File

@@ -9,15 +9,20 @@ import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Vec3f;
import net.minecraft.item.ModelTransformationMode;
import org.joml.AxisAngle4f;
import org.joml.Math;
import org.joml.Quaternionf;
import java.util.Objects;
@Environment(EnvType.CLIENT)
public class BrewingStandBlockEntityRenderer implements BlockEntityRenderer<BrewingStandBlockEntity> {
private static final Quaternionf degrees45 = new Quaternionf(new AxisAngle4f(Math.toRadians(45), 0, 1, 0));
private static final Quaternionf degrees180 = new Quaternionf(new AxisAngle4f(Math.toRadians(180), 0, 1, 0));
private static final Quaternionf degrees315 = new Quaternionf(new AxisAngle4f(Math.toRadians(315), 0, 1, 0));
public BrewingStandBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
}
@@ -37,28 +42,28 @@ public class BrewingStandBlockEntityRenderer implements BlockEntityRenderer<Brew
matrices.translate(0.86f, 0.23f, 0.5f);
matrices.scale(1.15f, 1.15f, 1.15f);
matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(180));
MinecraftClient.getInstance().getItemRenderer().renderItem(item1, ModelTransformation.Mode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, 0);
matrices.multiply(degrees180);
MinecraftClient.getInstance().getItemRenderer().renderItem(item1, ModelTransformationMode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, blockEntity.getWorld(), 0);
matrices.pop();
}
if (!item2.isEmpty()) {
matrices.push();
matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(315));
matrices.multiply(degrees315);
matrices.translate(0.32f, 0.23f, 0f);
matrices.scale(1.15f, 1.15f, 1.15f);
MinecraftClient.getInstance().getItemRenderer().renderItem(item2, ModelTransformation.Mode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, 0);
MinecraftClient.getInstance().getItemRenderer().renderItem(item2, ModelTransformationMode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, blockEntity.getWorld(), 0);
matrices.pop();
}
if (!item3.isEmpty()) {
matrices.push();
matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(45));
matrices.multiply(degrees45);
matrices.translate(-0.39f, 0.23f, 0.705f);
matrices.scale(1.15f, 1.15f, 1.15f);
MinecraftClient.getInstance().getItemRenderer().renderItem(item3, ModelTransformation.Mode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, 0);
MinecraftClient.getInstance().getItemRenderer().renderItem(item3, ModelTransformationMode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, blockEntity.getWorld(), 0);
matrices.pop();
}

View File

@@ -13,18 +13,21 @@ import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.tag.ItemTags;
import net.minecraft.item.ModelTransformationMode;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Vec3f;
import org.joml.AxisAngle4f;
import org.joml.Math;
import org.joml.Quaternionf;
import java.util.Objects;
@Environment(EnvType.CLIENT)
public class FurnaceBlockEntityRenderer<E extends AbstractFurnaceBlockEntity> implements BlockEntityRenderer<E> {
private static final Quaternionf degrees90x = new Quaternionf(new AxisAngle4f(Math.toRadians(90), 1, 0, 0));
private final FurnaceWoodenPlanksModel planks;
public FurnaceBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
@@ -35,42 +38,43 @@ public class FurnaceBlockEntityRenderer<E extends AbstractFurnaceBlockEntity> im
if (VOConfig.furnace && blockEntity != null) {
BlockState blockState = blockEntity.getCachedState();
int lightAtBlock = WorldRenderer.getLightmapCoordinates(Objects.requireNonNull(blockEntity.getWorld()), blockEntity.getPos().offset(blockState.get(AbstractFurnaceBlock.FACING)));
ItemStack item1 = blockEntity.getStack(0);
ItemStack item2 = blockEntity.getStack(1);
float angle = (blockState.get(AbstractFurnaceBlock.FACING)).asRotation();
ItemStack input = blockEntity.getStack(0);
ItemStack fuel = blockEntity.getStack(1);
ItemStack output = blockEntity.getStack(2);
float angle = (blockState.get(AbstractFurnaceBlock.FACING)).getRotationQuaternion().angle();
if(!item1.isEmpty()) {
if(!input.isEmpty() || !output.isEmpty()) {
matrices.push();
matrices.translate(0.5f, 0.58f, 0.5f);
if (blockEntity.getCachedState().getBlock().equals(Blocks.SMOKER)) matrices.translate(0f, -0.06f, 0f);
if (blockEntity.getCachedState().getBlock().equals(Blocks.BLAST_FURNACE)) matrices.translate(0f, -0.25f, 0f);
matrices.scale(1f, 1f, 1f);
matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(angle * 3 + 180));
matrices.multiply(new Quaternionf(new AxisAngle4f(Math.toRadians(angle * 3 + 180), 0, 1, 0)));
matrices.translate(0.0f, 0.0f, -0.4f);
matrices.multiply(Vec3f.POSITIVE_X.getDegreesQuaternion(90));
MinecraftClient.getInstance().getItemRenderer().renderItem(item1, ModelTransformation.Mode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, 0);
matrices.multiply(degrees90x);
MinecraftClient.getInstance().getItemRenderer().renderItem(input.isEmpty() ? output : input, ModelTransformationMode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, blockEntity.getWorld(), 0);
matrices.pop();
}
if (!item2.isEmpty() && !ItemTags.LOGS_THAT_BURN.contains(item2.getItem()) && !ItemTags.PLANKS.contains(item2.getItem())) {
if (!fuel.isEmpty() && !fuel.isIn(ItemTags.LOGS_THAT_BURN) && !fuel.isIn(ItemTags.PLANKS)) {
matrices.push();
matrices.translate(0.5f, 0.08f, 0.5f);
if (blockEntity.getCachedState().getBlock().equals(Blocks.SMOKER)) matrices.translate(0f, 0.06f, 0f);
if (blockEntity.getCachedState().getBlock().equals(Blocks.BLAST_FURNACE)) matrices.translate(0f, 0.24f, 0f);
matrices.scale(1f, 1f, 1f);
matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(angle * 3 + 180));
matrices.multiply(new Quaternionf(new AxisAngle4f(Math.toRadians(angle * 3 + 180), 0, 1, 0)));
matrices.translate(0.0f, 0.0f, -0.4f);
matrices.multiply(Vec3f.POSITIVE_X.getDegreesQuaternion(90));
MinecraftClient.getInstance().getItemRenderer().renderItem(item2, ModelTransformation.Mode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers,0);
matrices.multiply(degrees90x);
MinecraftClient.getInstance().getItemRenderer().renderItem(fuel, ModelTransformationMode.GROUND, lightAtBlock, overlay, matrices, vertexConsumers, blockEntity.getWorld(), 0);
matrices.pop();
}
else if (!item2.isEmpty()) {
else if (!fuel.isEmpty()) {
matrices.push();
BlockState state = Block.getBlockFromItem(item2.getItem()).getDefaultState();
BlockState state = Block.getBlockFromItem(fuel.getItem()).getDefaultState();
Sprite texture = MinecraftClient.getInstance().getBlockRenderManager().getModel(state).getParticleSprite();
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getEntityCutoutNoCull(spriteToTexture(texture)));
@@ -80,7 +84,7 @@ public class FurnaceBlockEntityRenderer<E extends AbstractFurnaceBlockEntity> im
matrices.scale(1f, 1f, 1f);
matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(angle * 3 + 180));
matrices.multiply(new Quaternionf(new AxisAngle4f(Math.toRadians(angle * 3 + 180), 0, 1, 0)));
planks.getPart().render(matrices, vertexConsumer, lightAtBlock, overlay);
matrices.pop();
}
@@ -88,7 +92,7 @@ public class FurnaceBlockEntityRenderer<E extends AbstractFurnaceBlockEntity> im
}
public static Identifier spriteToTexture(Sprite sprite) {
String texture = sprite.getId().getPath();
return new Identifier(sprite.getId().getNamespace(), "textures/" + texture + ".png");
String texture = sprite.getContents().getId().getPath();
return Identifier.of(sprite.getAtlasId().getNamespace(), "textures/" + texture + ".png");
}
}

View File

@@ -0,0 +1,75 @@
package eu.midnightdust.visualoverhaul.block.renderer;
import eu.midnightdust.visualoverhaul.FakeBlocks;
import eu.midnightdust.visualoverhaul.VisualOverhaulClient;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import eu.midnightdust.visualoverhaul.util.SoundTest;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.BlockState;
import net.minecraft.block.SideShapeType;
import net.minecraft.block.entity.JukeboxBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.state.property.Properties;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import org.joml.AxisAngle4f;
import org.joml.Math;
import org.joml.Quaternionf;
import java.util.Objects;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.id;
import static eu.midnightdust.visualoverhaul.VisualOverhaulCommon.jukeboxItems;
@Environment(EnvType.CLIENT)
public class JukeboxBlockEntityRenderer implements BlockEntityRenderer<JukeboxBlockEntity> {
public JukeboxBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {}
@Override
public void render(JukeboxBlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
if (VOConfig.jukebox) {
int lightAbove = WorldRenderer.getLightmapCoordinates(Objects.requireNonNull(blockEntity.getWorld()), blockEntity.getPos().up());
Identifier discModel = null; // If the sound is stopped or no sound is playing, no model is set //
// Tries to get the disc using the serverside method
if (jukeboxItems.containsKey(blockEntity.getPos()) && !jukeboxItems.get(blockEntity.getPos()).isEmpty()) {
discModel = RoundDiscRenderer.getModelId(jukeboxItems.get(blockEntity.getPos()));
}
// Else gets the record sound played at the position of the jukebox //
else if (SoundTest.getSound(blockEntity.getPos()) != null) {
// Converts the Sound ID to the item ID of the appropriate disc (minecraft:music_disc.cat -> minecraft:music_disc_cat) //
discModel = Identifier.of(String.valueOf(SoundTest.getSound(blockEntity.getPos())).replace(".", "_"));
}
if (discModel != null) {
matrices.push();
matrices.translate(0.5f, 1.03f, 0.5f);
matrices.scale(0.75f, 0.75f, 0.75f);
matrices.multiply(new Quaternionf(new AxisAngle4f(Math.toRadians(Util.getMeasuringTimeMs() / 9.0f), 0, 1, 0)));
RoundDiscRenderer.render(discModel, lightAbove, overlay, matrices, vertexConsumers);
matrices.pop();
}
if (VOConfig.jukebox_fake_block && !blockEntity.getWorld().getBlockState(blockEntity.getPos().up()).isSideSolid(blockEntity.getWorld(),blockEntity.getPos().up(), Direction.DOWN, SideShapeType.FULL)) {
matrices.push();
matrices.translate(0f, 1f, 0f);
Identifier blockId = discModel != null ? id("jukebox_top_playing") : id("jukebox_top_stopped");
FakeBlocks.renderFakeBlock(blockId, blockEntity.getPos().up(), blockEntity.getWorld(), matrices, vertexConsumers.getBuffer(RenderLayer.getCutout()));
matrices.pop();
}
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
package eu.midnightdust.visualoverhaul.config;
import eu.midnightdust.lib.config.MidnightConfig;
public class VOConfig extends MidnightConfig {
public static final String blocks = "blocks";
public static final String colors = "colors";
public static final String gui = "gui";
@Client @Entry(category = blocks) public static boolean brewingstand = true;
@Client @Entry(category = blocks) public static boolean jukebox = true;
@Client @Entry(category = blocks) public static boolean jukebox_fake_block = true;
@Client @Entry(category = blocks) public static boolean jukebox_clientside = true;
@Client @Entry(category = blocks) public static boolean furnace = true;
@Client @Entry(category = blocks) public static boolean smoker_particles = true;
@Client @Entry(category = blocks) public static boolean blast_furnace_particles = true;
@Client @Entry(category = colors) public static boolean coloredItems = true;
@Client @Entry(category = colors) public static boolean coloredLilypad = true;
@Client @Entry(category = gui) public static boolean buttonIcons = false;
@Client @Entry(category = gui) public static IconPosition buttonIconPosition = IconPosition.LOCATION;
@Client @Entry(category = gui) public static boolean zoomIconOnHover = true;
@Client @Entry(category = gui, name = "Debug") public static boolean debug = false;
@Client @Entry @Hidden public static boolean firstLaunch = true;
public enum IconPosition {LOCATION, LEFT, RIGHT, BOTH}
}

View File

@@ -0,0 +1,12 @@
package eu.midnightdust.visualoverhaul.mixin;
import net.minecraft.client.render.item.ItemRenderState;
import net.minecraft.item.ModelTransformationMode;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ItemRenderState.class)
public interface ItemRenderStateAccessor {
@Accessor("modelTransformationMode")
void setModelTransformationMode(ModelTransformationMode modelTransformationMode);
}

View File

@@ -7,14 +7,13 @@ import net.minecraft.block.BlockState;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
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;
import java.util.Random;
@Mixin(BlastFurnaceBlock.class)
public abstract class MixinBlastFurnaceBlock extends AbstractFurnaceBlock {
protected MixinBlastFurnaceBlock(Settings settings) {

View File

@@ -0,0 +1,25 @@
package eu.midnightdust.visualoverhaul.mixin;
import eu.midnightdust.visualoverhaul.VisualOverhaulClient;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.minecraft.client.render.item.tint.ConstantTintSource;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
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 java.util.Objects;
@Mixin(ConstantTintSource.class)
public abstract class MixinConstantTintSource {
@Inject(at = @At("RETURN"), method = "getTint", cancellable = true)
public void vo$modifyLeafTint(ItemStack stack, ClientWorld world, LivingEntity user, CallbackInfoReturnable<Integer> cir) {
// Dynamic Leaf Item colors
if (VOConfig.coloredItems && Objects.equals(-12012264, cir.getReturnValue())) {
cir.setReturnValue(VisualOverhaulClient.foliageColor);
}
}
}

View File

@@ -0,0 +1,23 @@
package eu.midnightdust.visualoverhaul.mixin;
import eu.midnightdust.visualoverhaul.VisualOverhaulClient;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.minecraft.client.render.item.tint.GrassTintSource;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
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;
@Mixin(GrassTintSource.class)
public abstract class MixinGrassTintSource {
@Inject(at = @At("RETURN"), method = "getTint", cancellable = true)
public void vo$modifyGrassTint(ItemStack stack, ClientWorld world, LivingEntity user, CallbackInfoReturnable<Integer> cir) {
// Dynamic Grass Item colors
if (VOConfig.coloredItems) {
cir.setReturnValue(VisualOverhaulClient.grassColor);
}
}
}

View File

@@ -0,0 +1,23 @@
package eu.midnightdust.visualoverhaul.mixin;
import eu.midnightdust.visualoverhaul.util.JukeboxPacketUpdate;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.*;
import net.minecraft.util.math.BlockPos;
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(JukeboxBlockEntity.class)
public abstract class MixinJukeboxBlockEntity extends BlockEntity {
public MixinJukeboxBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Inject(at = @At("TAIL"), method = "onRecordStackChanged")
public void getRecord(CallbackInfo ci) {
JukeboxPacketUpdate.invUpdate = true;
}
}

View File

@@ -0,0 +1,39 @@
package eu.midnightdust.visualoverhaul.mixin;
import eu.midnightdust.visualoverhaul.VisualOverhaulClient;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.minecraft.client.render.item.tint.PotionTintSource;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.Potion;
import net.minecraft.potion.Potions;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.math.ColorHelper;
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.CallbackInfoReturnable;
import java.util.List;
@Mixin(PotionTintSource.class)
public class MixinPotionTintSource {
@Unique private static final List<RegistryEntry<Potion>> WATER_POTIONS = List.of(Potions.WATER, Potions.MUNDANE, Potions.THICK, Potions.AWKWARD);
@Inject(at = @At("RETURN"), method = "getTint", cancellable = true)
public void vo$modifyWaterTint(ItemStack stack, ClientWorld world, LivingEntity user, CallbackInfoReturnable<Integer> cir) {
// Dynamic Potion Item colors
if (VOConfig.coloredItems) {
var contents = stack.getComponents().get(DataComponentTypes.POTION_CONTENTS);
if (contents != null && contents.potion().isPresent()) {
if (!WATER_POTIONS.contains(contents.potion().get()))
return; // Skip all potions with effects
}
if (cir.getReturnValue() == -1) cir.setReturnValue(ColorHelper.fullAlpha(VisualOverhaulClient.potionColor));
else cir.setReturnValue(VisualOverhaulClient.potionColor);
}
}
}

View File

@@ -0,0 +1,29 @@
package eu.midnightdust.visualoverhaul.mixin;
import eu.midnightdust.visualoverhaul.IconicButtons;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.PressableWidget;
import net.minecraft.text.Text;
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;
@Mixin(PressableWidget.class)
public abstract class MixinPressableWidget extends ClickableWidget {
@Unique IconicButtons visualoverhaul$iconicButtons;
public MixinPressableWidget(int x, int y, int width, int height, Text message) {
super(x, y, width, height, message);
}
@Inject(at = @At("TAIL"), method = "<init>")
private void iconic$onInitButton(int i, int j, int k, int l, Text text, CallbackInfo ci) {
visualoverhaul$iconicButtons = new IconicButtons();
}
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/PressableWidget;drawMessage(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/font/TextRenderer;I)V", shift = At.Shift.BEFORE), method = "renderWidget")
private void iconic$onRenderButton(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
visualoverhaul$iconicButtons.renderIcons(context, this, this.alpha);
}
}

View File

@@ -0,0 +1,29 @@
package eu.midnightdust.visualoverhaul.mixin;
import eu.midnightdust.visualoverhaul.IconicButtons;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.text.Text;
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;
@Mixin(SliderWidget.class)
public abstract class MixinSliderWidget extends ClickableWidget {
@Unique IconicButtons visualoverhaul$iconicButtons;
public MixinSliderWidget(int x, int y, int width, int height, Text message) {
super(x, y, width, height, message);
}
@Inject(at = @At("TAIL"), method = "<init>")
private void iconic$onInitButton(int x, int y, int width, int height, Text text, double value, CallbackInfo ci) {
visualoverhaul$iconicButtons = new IconicButtons();
}
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/SliderWidget;drawScrollableText(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/font/TextRenderer;II)V", shift = At.Shift.BEFORE), method = "renderWidget")
private void iconic$onRenderButton(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
visualoverhaul$iconicButtons.renderIcons(context, this, this.alpha);
}
}

View File

@@ -7,14 +7,13 @@ import net.minecraft.block.SmokerBlock;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
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;
import java.util.Random;
@Mixin(SmokerBlock.class)
public abstract class MixinSmokerBlock extends AbstractFurnaceBlock {
protected MixinSmokerBlock(Settings settings) {

View File

@@ -7,6 +7,7 @@ import net.minecraft.sound.SoundCategory;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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;
@@ -16,13 +17,16 @@ public abstract class MixinSoundSystem {
@Shadow private boolean started;
private BlockPos jukeboxPos;
@Unique
private BlockPos visualoverhaul$jukeboxPos;
@Inject(at = @At("TAIL"),method = "play(Lnet/minecraft/client/sound/SoundInstance;)V")
public void vo$onPlayRecordSound(SoundInstance soundInstance, CallbackInfo ci) {
if (soundInstance.getCategory().equals(SoundCategory.RECORDS) && this.started) {
jukeboxPos = new BlockPos(soundInstance.getX(),soundInstance.getY(),soundInstance.getZ());
SoundTest.soundPos.put(jukeboxPos, soundInstance.getId());
if (soundInstance != null) {
if (soundInstance.getCategory().equals(SoundCategory.RECORDS) && this.started) {
visualoverhaul$jukeboxPos = BlockPos.ofFloored(Math.floor(soundInstance.getX()), Math.floor(soundInstance.getY()), Math.floor(soundInstance.getZ()));
SoundTest.soundPos.put(visualoverhaul$jukeboxPos, soundInstance.getId());
}
}
}
@@ -30,9 +34,9 @@ public abstract class MixinSoundSystem {
public void vo$onStopRecordSound(SoundInstance soundInstance, CallbackInfo ci) {
if (soundInstance != null) {
if (soundInstance.getCategory().equals(SoundCategory.RECORDS)) {
jukeboxPos = new BlockPos(soundInstance.getX(), soundInstance.getY(), soundInstance.getZ());
if (SoundTest.soundPos.containsKey(jukeboxPos)) {
SoundTest.soundPos.remove(jukeboxPos, soundInstance.getId());
visualoverhaul$jukeboxPos = BlockPos.ofFloored(Math.floor(soundInstance.getX()), Math.floor(soundInstance.getY()), Math.floor(soundInstance.getZ()));
if (SoundTest.soundPos.containsKey(visualoverhaul$jukeboxPos)) {
SoundTest.soundPos.remove(visualoverhaul$jukeboxPos, soundInstance.getId());
}
}
}

View File

@@ -0,0 +1,19 @@
package eu.midnightdust.visualoverhaul.mixin;
import net.minecraft.client.texture.AbstractTexture;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Map;
@Mixin(TextureManager.class)
public interface TextureManagerAccessor {
@Accessor
ResourceManager getResourceContainer();
@Accessor
Map<Identifier, AbstractTexture> getTextures();
}

View File

@@ -0,0 +1,27 @@
package eu.midnightdust.visualoverhaul.packet;
import eu.midnightdust.visualoverhaul.VisualOverhaulCommon;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.packet.CustomPayload;
import java.util.UUID;
public record HelloPacket(UUID uuid) implements CustomPayload {
public static final CustomPayload.Id<HelloPacket> PACKET_ID = new CustomPayload.Id<>(VisualOverhaulCommon.HELLO_PACKET);
public static final PacketCodec<PacketByteBuf, HelloPacket> codec = PacketCodec.of(HelloPacket::write, HelloPacket::read);
public static HelloPacket read(PacketByteBuf buf) {
return new HelloPacket(buf.readUuid());
}
public void write(PacketByteBuf buf) {
buf.writeUuid(uuid);
}
@Override
public Id<? extends CustomPayload> getId() {
return PACKET_ID;
}
}

View File

@@ -0,0 +1,30 @@
package eu.midnightdust.visualoverhaul.packet;
import eu.midnightdust.visualoverhaul.VisualOverhaulCommon;
import net.minecraft.item.ItemStack;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
public record UpdateItemsPacket(Identifier blockTypeID, BlockPos pos, DefaultedList<ItemStack> inv) implements CustomPayload {
public static final Id<UpdateItemsPacket> PACKET_ID = new Id<>(VisualOverhaulCommon.UPDATE_ITEMS_PACKET);
public static final PacketCodec<RegistryByteBuf, UpdateItemsPacket> codec = PacketCodec.of(UpdateItemsPacket::write, UpdateItemsPacket::read);
public static UpdateItemsPacket read(RegistryByteBuf buf) {
return new UpdateItemsPacket(buf.readIdentifier(), buf.readBlockPos(), (DefaultedList<ItemStack>) ItemStack.OPTIONAL_LIST_PACKET_CODEC.decode(buf));
}
public void write(RegistryByteBuf buf) {
buf.writeIdentifier(blockTypeID);
buf.writeBlockPos(pos);
ItemStack.OPTIONAL_LIST_PACKET_CODEC.encode(buf, this.inv);
}
@Override
public Id<? extends CustomPayload> getId() {
return PACKET_ID;
}
}

View File

@@ -0,0 +1,63 @@
package eu.midnightdust.visualoverhaul.util;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.fabricmc.loader.api.FabricLoader;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture;
import org.apache.commons.lang3.Validate;
import org.spongepowered.asm.mixin.Unique;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class ModIconUtil {
private static final Map<Path, NativeImageBackedTexture> modIconCache = new HashMap<>();
private final String modid;
public ModIconUtil(String modid) {
this.modid = modid;
}
@ExpectPlatform
public static Path getPath(String modid) {
throw new AssertionError();
}
@Unique
public NativeImageBackedTexture createModIcon() {
try {
Path path = getPath(modid);
if (VOConfig.debug) System.out.println(path);
NativeImageBackedTexture cachedIcon = getCachedModIcon(path);
if (cachedIcon != null) {
return cachedIcon;
}
cachedIcon = getCachedModIcon(path);
if (cachedIcon != null) {
return cachedIcon;
}
try (InputStream inputStream = Files.newInputStream(path)) {
NativeImage image = NativeImage.read(Objects.requireNonNull(inputStream));
Validate.validState(image.getHeight() == image.getWidth(), "Must be square icon");
NativeImageBackedTexture tex = new NativeImageBackedTexture(image);
cacheModIcon(path, tex);
return tex;
}
} catch (Throwable t) {
if (VOConfig.debug) System.out.println(t.getMessage());
return null;
}
}
static NativeImageBackedTexture getCachedModIcon(Path path) {
return modIconCache.get(path);
}
static void cacheModIcon(Path path, NativeImageBackedTexture tex) {
modIconCache.put(path, tex);
}
}

View File

@@ -1,6 +1,7 @@
package eu.midnightdust.visualoverhaul.util;
import com.google.common.collect.Maps;
import eu.midnightdust.visualoverhaul.config.VOConfig;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
@@ -15,7 +16,7 @@ public class SoundTest {
* {@link eu.midnightdust.visualoverhaul.mixin.MixinSoundSystem}
*/
public static Identifier getSound(BlockPos pos) {
if (soundPos.containsKey(pos)) {
if (VOConfig.jukebox_clientside && soundPos.containsKey(pos)) {
return soundPos.get(pos);
}
return null;

View File

@@ -0,0 +1,17 @@
package eu.midnightdust.visualoverhaul.util;
import net.minecraft.util.math.ColorHelper;
import net.minecraft.util.math.MathHelper;
public class VOColorUtil {
public static int convertRgbToArgb(int rgb, int alpha) {
int red = 0xFF & (rgb >> 16);
int green = 0xFF & (rgb >> 8);
int blue = 0xFF & (rgb);
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
public static int alphaAndBrightness(float alpha, float brightness) {
return ColorHelper.getArgb(MathHelper.floor(alpha*255), MathHelper.floor(brightness*255), MathHelper.floor(brightness*255), MathHelper.floor(brightness*255));
}
}

View File

@@ -0,0 +1,2 @@
{
}

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.done.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/written_book.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/paper.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/knowledge_book.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/modmenu.title.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/experience_bottle.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.cancel.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/coal.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/emerald.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/block/redstone_lamp.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.done.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/paper.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/block/redstone_lamp_on.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/menu.returntomenu.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/diamond_sword.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/netherite_hoe.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/command_block_minecart.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/mangrove_sign.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/barrier.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/pufferfish.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/emerald.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/blaze_powder.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/echo_shard.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/recovery_compass_18.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/iron_pickaxe.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.no.properties

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.yes.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/totem_of_undying.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/axolotl_bucket.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/birch_hanging_sign.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/jungle_boat.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/name_tag.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/ender_eye.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/writable_book.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/comparator.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/painting.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/armor_stand.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/music_disc_otherside.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/nether_star.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/end_crystal.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/mojang_banner_pattern.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/slime_ball.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/selectworld.create.properties

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/selectworld.delete.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/firework_rocket.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/selectworld.edit.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/blaze_powder.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/selectworld.select.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/diamond.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/tnt_minecart.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/menu.options.properties

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.done.properties

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/furnace_minecart.png

View File

@@ -0,0 +1 @@
texture=minecraft:textures/item/trident.png

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.no.properties

View File

@@ -0,0 +1 @@
properties=iconic:textures/gui/icons/gui.yes.properties

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1,23 @@
{
"visualoverhaul.midnightconfig.title":"Visual Overhaul Konfiguration",
"visualoverhaul.midnightconfig.brewingstand":"Braustand-Verbesserungen",
"visualoverhaul.midnightconfig.jukebox":"Jukebox-Verbesserungen",
"visualoverhaul.midnightconfig.jukebox_fake_block":"Fake-Block auf der Jukebox",
"visualoverhaul.midnightconfig.furnace":"Ofen-Verbesserungen",
"visualoverhaul.midnightconfig.smoker_particles":"Räucherofen-Partikel",
"visualoverhaul.midnightconfig.blast_furnace_particles":"Schmelzofen-Partikel",
"visualoverhaul.midnightconfig.coloredItems":"Biom-basierte Item-Farben",
"visualoverhaul.midnightconfig.coloredItems.tooltip":"§cNeustart benötigt!",
"visualoverhaul.midnightconfig.coloredLilypad":"Biom-basierte Seerosenfarbe",
"visualoverhaul.midnightconfig.coloredLilypad.tooltip":"§cNeustart benötigt!",
"visualoverhaul.midnightconfig.buttonIcons": "Symbole auf Knöpfen",
"visualoverhaul.midnightconfig.buttonIconPosition": "Knopfsymbolposition",
"visualoverhaul.midnightconfig.enum.IconPosition.LOCATION": "Ortsbasiert",
"visualoverhaul.midnightconfig.enum.IconPosition.LEFT": "Links",
"visualoverhaul.midnightconfig.enum.IconPosition.RIGHT": "Rechts",
"visualoverhaul.midnightconfig.enum.IconPosition.BOTH": "Links & Rechts",
"visualoverhaul.midnightconfig.zoomIconOnHover": "Vergrößere Symbol beim Überfahren",
"visualoverhaul.midnightconfig.category.gui": "GUI",
"visualoverhaul.midnightconfig.category.blocks": "Blöcke",
"visualoverhaul.midnightconfig.category.colors": "Farben"
}

View File

@@ -0,0 +1,25 @@
{
"visualoverhaul.midnightconfig.title":"Visual Overhaul Config",
"visualoverhaul.midnightconfig.brewingstand":"Brewing Stand Enhancements",
"visualoverhaul.midnightconfig.jukebox":"Jukebox Enhancements",
"visualoverhaul.midnightconfig.jukebox_fake_block":"Fake block on jukebox top",
"visualoverhaul.midnightconfig.jukebox_clientside":"Client-side music disc detection",
"visualoverhaul.midnightconfig.jukebox_clientside.tooltip":"Might not be 100% accurate with custom music discs.",
"visualoverhaul.midnightconfig.furnace":"Furnace Enhancements",
"visualoverhaul.midnightconfig.smoker_particles":"Smoker Particles",
"visualoverhaul.midnightconfig.blast_furnace_particles":"Blast Furnace Particles",
"visualoverhaul.midnightconfig.coloredItems":"Biome-based item colors",
"visualoverhaul.midnightconfig.coloredItems.tooltip":"§cNeeds restart!",
"visualoverhaul.midnightconfig.coloredLilypad":"Biome-based Lily Pad color",
"visualoverhaul.midnightconfig.coloredLilypad.tooltip":"§cNeeds restart!",
"visualoverhaul.midnightconfig.buttonIcons": "Button Icons",
"visualoverhaul.midnightconfig.buttonIconPosition": "Button Icon Position",
"visualoverhaul.midnightconfig.enum.IconPosition.LOCATION": "Location-dependant",
"visualoverhaul.midnightconfig.enum.IconPosition.LEFT": "Left",
"visualoverhaul.midnightconfig.enum.IconPosition.RIGHT": "Right",
"visualoverhaul.midnightconfig.enum.IconPosition.BOTH": "Left & Right",
"visualoverhaul.midnightconfig.zoomIconOnHover": "Zoom icon on hover",
"visualoverhaul.midnightconfig.category.gui": "GUI",
"visualoverhaul.midnightconfig.category.blocks": "Blocks",
"visualoverhaul.midnightconfig.category.colors": "Colors"
}

View File

@@ -0,0 +1,23 @@
{
"visualoverhaul.midnightconfig.title":"Configuración de Visual Overhaul",
"visualoverhaul.midnightconfig.brewingstand":"Mejoras en el soporte de pociones",
"visualoverhaul.midnightconfig.jukebox":"Mejoras en la caja de música",
"visualoverhaul.midnightconfig.jukebox_fake_block":"Bloque falso en la parte superior de la caja de música",
"visualoverhaul.midnightconfig.furnace":"Mejoras en el horno",
"visualoverhaul.midnightconfig.smoker_particles":"Partículas de ahumador",
"visualoverhaul.midnightconfig.blast_furnace_particles":"Partículas del alto horno",
"visualoverhaul.midnightconfig.coloredItems":"Colores de objetos basados en el bioma",
"visualoverhaul.midnightconfig.coloredItems.tooltip":"§c¡Necesita reiniciar!",
"visualoverhaul.midnightconfig.coloredLilypad":"Color de nenúfar basado en el bioma",
"visualoverhaul.midnightconfig.coloredLilypad.tooltip":"§c¡Necesita reiniciar!",
"visualoverhaul.midnightconfig.buttonIcons": "Iconos de botones",
"visualoverhaul.midnightconfig.buttonIconPosition": "Posición del icono del botón",
"visualoverhaul.midnightconfig.enum.IconPosition.LOCATION": "Dependiente de la ubicación",
"visualoverhaul.midnightconfig.enum.IconPosition.LEFT": "Izquierda",
"visualoverhaul.midnightconfig.enum.IconPosition.RIGHT": "Derecha",
"visualoverhaul.midnightconfig.enum.IconPosition.BOTH": "Izquierda y derecha",
"visualoverhaul.midnightconfig.zoomIconOnHover": "Icono de zoom al pasar el cursor",
"visualoverhaul.midnightconfig.category.gui": "GUI",
"visualoverhaul.midnightconfig.category.blocks": "Bloques",
"visualoverhaul.midnightconfig.category.colors": "Colores"
}

View File

@@ -0,0 +1,13 @@
{
"visualoverhaul.midnightconfig.title":"Configuration de Visual Overhaul",
"visualoverhaul.midnightconfig.brewingstand":"Améliorations de l'Alambic",
"visualoverhaul.midnightconfig.jukebox":"Améliorations du Jukebox",
"visualoverhaul.midnightconfig.jukebox_fake_block":"Faux bloc sur le dessus du Jukebox",
"visualoverhaul.midnightconfig.furnace":"Améliorations du Four",
"visualoverhaul.midnightconfig.smoker_particles":"Particles du Fumoir",
"visualoverhaul.midnightconfig.blast_furnace_particles":"Particles du Haut Fourneau",
"visualoverhaul.midnightconfig.coloredItems":"Couleurs des objets basées sur le biome",
"visualoverhaul.midnightconfig.coloredItems.tooltip":"§cBesoin de redémarrer !",
"visualoverhaul.midnightconfig.coloredLilypad":"Couleur de nénuphar basée sur le biome",
"visualoverhaul.midnightconfig.coloredLilypad.tooltip":"§cBesoin de redémarrer !"
}

View File

@@ -0,0 +1,25 @@
{
"visualoverhaul.midnightconfig.title": "《視覺增強》設定",
"visualoverhaul.midnightconfig.brewingstand": "釀造台增強",
"visualoverhaul.midnightconfig.jukebox": "唱片機增強",
"visualoverhaul.midnightconfig.jukebox_fake_block": "唱片機頂部的偽裝方塊",
"visualoverhaul.midnightconfig.jukebox_clientside": "用戶端音樂唱片偵測",
"visualoverhaul.midnightconfig.jukebox_clientside.tooltip": "對於自訂音樂唱片,可能無法 100% 準確。",
"visualoverhaul.midnightconfig.furnace": "熔爐增強",
"visualoverhaul.midnightconfig.smoker_particles": "煙燻爐粒子",
"visualoverhaul.midnightconfig.blast_furnace_particles": "高爐粒子",
"visualoverhaul.midnightconfig.coloredItems": "基於生態域的物品顏色",
"visualoverhaul.midnightconfig.coloredItems.tooltip": "§c需要重新啟動",
"visualoverhaul.midnightconfig.coloredLilypad": "基於生態域的睡蓮顏色",
"visualoverhaul.midnightconfig.coloredLilypad.tooltip": "§c需要重新啟動",
"visualoverhaul.midnightconfig.buttonIcons": "按鈕圖示",
"visualoverhaul.midnightconfig.buttonIconPosition": "按鈕圖示位置",
"visualoverhaul.midnightconfig.enum.IconPosition.LOCATION": "取決於位置",
"visualoverhaul.midnightconfig.enum.IconPosition.LEFT": "左",
"visualoverhaul.midnightconfig.enum.IconPosition.RIGHT": "右",
"visualoverhaul.midnightconfig.enum.IconPosition.BOTH": "左和右",
"visualoverhaul.midnightconfig.zoomIconOnHover": "懸停時放大圖示",
"visualoverhaul.midnightconfig.category.gui": "介面",
"visualoverhaul.midnightconfig.category.blocks": "方塊",
"visualoverhaul.midnightconfig.category.colors": "顏色"
}

Some files were not shown because too many files have changed in this diff Show More