Compare commits

...
8 Commits
30 changed files with 480 additions and 147 deletions

No files matched your search

+2
View File
@@ -28,3 +28,5 @@ whitelist.json
src/main/resources/mixins.*.json src/main/resources/mixins.*.json
*.bat *.bat
.DS_Store .DS_Store
*.sh
+7
View File
@@ -6,3 +6,10 @@ minecraft {
} }
} }
} }
test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
+3 -1
View File
@@ -1,5 +1,7 @@
// Add your dependencies here // Add your dependencies here
dependencies { dependencies {
shadowImplementation("com.github.GTNewHorizons:GTNHLib:0.11.5") testImplementation(platform('org.junit:junit-bom:5.14.1'))
testImplementation('org.junit.jupiter:junit-jupiter')
testRuntimeOnly('org.junit.platform:junit-platform-launcher')
} }
+6 -1
View File
@@ -133,7 +133,7 @@ forceEnableMixins = false
# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your # If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your
# responsibility to check the license and request permission for distribution if required. # responsibility to check the license and request permission for distribution if required.
usesShadowedDependencies = true usesShadowedDependencies = false
# If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access # If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access
# their own classes, making the minimization unreliable. # their own classes, making the minimization unreliable.
@@ -180,6 +180,11 @@ modrinthRelations =
# Leave this empty if you don't want to publish on CurseForge. # Leave this empty if you don't want to publish on CurseForge.
curseForgeProjectId = 746279 curseForgeProjectId = 746279
# Comma-separated supported CurseForge environments: client, server (case-insensitive).
# Use client or server for mods that only support one environment. Defaults to client,server.
# These tags describe where the mod can run, not whether installation is required on both sides.
curseForgeEnvironments = client,server
# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. # The project's relations on CurseForge. You can use this to refer to other projects on CurseForge.
# Syntax: type1:name1;type2:name2;... # Syntax: type1:name1;type2:name2;...
# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], # Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible],
+10 -10
View File
@@ -1,12 +1,12 @@
#This file is generated by updateDaemonJvm #This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c5ee947fbfb70bc347d8d531e3a578c4/redirect toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/539ea72837c6244075f8ee037babc29e/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/876dbbf00bf4ef6190f7da074cee903a/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/539ea72837c6244075f8ee037babc29e/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/876dbbf00bf4ef6190f7da074cee903a/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/d4fd992c9557644e637ebe98263e0ae7/redirect toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/9064f22734b42ac03e85df04b632e167/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/59a9771cad43219260d9aac9a8ec4d6a/redirect toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/4d0277c49991306ac78048580fe34bcf/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c5ee947fbfb70bc347d8d531e3a578c4/redirect toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/539ea72837c6244075f8ee037babc29e/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/876dbbf00bf4ef6190f7da074cee903a/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/a4c09dd2e2d7079373d30e524bbc2829/redirect toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/a9fa3b809e484a1e1ac4308a5dda661a/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/8e1d9ee5d0f13e442218f6884a306da1/redirect toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/aa99913fa6d767d899ffc96082da01ca/redirect
toolchainVersion=25 toolchainVersion=25
Binary file not shown.
+3 -1
View File
@@ -1,7 +1,9 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
networkTimeout=10000 networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Vendored
+3 -3
View File
@@ -20,7 +20,7 @@
############################################################################## ##############################################################################
# #
# Gradle start up script for POSIX generated by Gradle. # gradlew start up script for POSIX generated by Gradle.
# #
# Important for running: # Important for running:
# #
@@ -29,7 +29,7 @@
# bash, then to run this script, type that shell name before the whole # bash, then to run this script, type that shell name before the whole
# command line, like: # command line, like:
# #
# ksh Gradle # ksh gradlew
# #
# Busybox and similar reduced shells will NOT work, because this script # Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features: # requires all of these POSIX shell features:
@@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
Vendored
+12 -23
View File
@@ -19,12 +19,12 @@
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@rem Gradle startup script for Windows @rem gradlew startup script for Windows
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables, and ensure extensions are enabled
if "%OS%"=="Windows_NT" setlocal setlocal EnableExtensions
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@@ -51,7 +51,7 @@ echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2 echo location of your Java installation. 1>&2
goto fail "%COMSPEC%" /c exit 1
:findJavaFromJavaHome :findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
@@ -65,29 +65,18 @@ echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2 echo location of your Java installation. 1>&2
goto fail "%COMSPEC%" /c exit 1
:execute :execute
@rem Setup the command line @rem Setup the command line
@rem Execute Gradle @rem Execute gradlew
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* @rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
:end :exitWithErrorLevel
@rem End local scope for the variables with windows NT shell @rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
if %ERRORLEVEL% equ 0 goto mainEnd "%COMSPEC%" /c exit %ERRORLEVEL%
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
} }
plugins { plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.24' id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.30'
} }
@@ -116,6 +116,7 @@ public class ClassDiscoverer {
while (zipEntries.hasMoreElements()) { while (zipEntries.hasMoreElements()) {
ZipEntry zipentry = zipEntries.nextElement(); ZipEntry zipentry = zipEntries.nextElement();
String fullname = zipentry.getName().replace('\\', '/'); String fullname = zipentry.getName().replace('\\', '/');
if (fullname.startsWith("META-INF/versions/")) continue;
int pos = fullname.lastIndexOf('/'); int pos = fullname.lastIndexOf('/');
String name = pos == -1 ? fullname : fullname.substring(pos + 1); String name = pos == -1 ? fullname : fullname.substring(pos + 1);
if (!zipentry.isDirectory() && matcher.matches(name)) { if (!zipentry.isDirectory() && matcher.matches(name)) {
@@ -2,12 +2,16 @@ package codechicken.core;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.EnumChatFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import codechicken.core.internal.CCCEventHandler; import codechicken.core.internal.CCCEventHandler;
import codechicken.lib.colour.LocalizedColours;
import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
@@ -65,4 +69,16 @@ public class ClientUtils extends CommonUtils {
.replace("Supporters:", EnumChatFormatting.AQUA + "Supporters:"); .replace("Supporters:", EnumChatFormatting.AQUA + "Supporters:");
GuiModListScroll.register(mod); GuiModListScroll.register(mod);
} }
@SideOnly(Side.CLIENT)
public static void registerLocalizedColourReloadListener() {
((IReloadableResourceManager) mc().getResourceManager())
.registerReloadListener(new IResourceManagerReloadListener() {
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
LocalizedColours.reloadLocalizedColours();
}
});
}
} }
@@ -36,7 +36,7 @@ import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import codechicken.core.launch.CodeChickenCorePlugin; import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.lib.colour.ColorUtils; import codechicken.lib.colour.LocalizedColours;
import codechicken.lib.gui.GuiDraw; import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i; import codechicken.lib.vec.Rectangle4i;
import cpw.mods.fml.client.GuiModList; import cpw.mods.fml.client.GuiModList;
@@ -149,12 +149,11 @@ public class GuiModListScroll {
double dy = scroll % (height + 20); double dy = scroll % (height + 20);
GL11.glPushMatrix(); GL11.glPushMatrix();
GL11.glTranslated(0, -dy, 0); GL11.glTranslated(0, -dy, 0);
GuiDraw.fontRenderer GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, LocalizedColours.MOD_DESCRIPTION_TEXT);
.drawSplitString(description, x1, y1draw, x2 - x1, ColorUtils.modDescriptionText.getColor());
if (needsScroll) { if (needsScroll) {
GL11.glTranslated(0, height + 20, 0); GL11.glTranslated(0, height + 20, 0);
GuiDraw.fontRenderer GuiDraw.fontRenderer
.drawSplitString(description, x1, y1draw, x2 - x1, ColorUtils.modDescriptionText.getColor()); .drawSplitString(description, x1, y1draw, x2 - x1, LocalizedColours.MOD_DESCRIPTION_TEXT);
} }
GL11.glPopMatrix(); GL11.glPopMatrix();
@@ -65,6 +65,8 @@ public class CodeChickenCoreModContainer extends DummyModContainer {
public void init(FMLInitializationEvent event) { public void init(FMLInitializationEvent event) {
if (event.getSide().isClient()) { if (event.getSide().isClient()) {
ClientUtils.enhanceSupportersList("CodeChickenCore"); ClientUtils.enhanceSupportersList("CodeChickenCore");
ClientUtils.registerLocalizedColourReloadListener();
FMLCommonHandler.instance().bus().register(new CCCEventHandler()); FMLCommonHandler.instance().bus().register(new CCCEventHandler());
MinecraftForge.EVENT_BUS.register(new CCCEventHandler()); MinecraftForge.EVENT_BUS.register(new CCCEventHandler());
} }
@@ -6,7 +6,7 @@ import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import codechicken.lib.colour.ColorUtils; import codechicken.lib.colour.LocalizedColours;
public class GuiCCButton extends GuiWidget { public class GuiCCButton extends GuiWidget {
@@ -75,9 +75,8 @@ public class GuiCCButton extends GuiWidget {
} }
public int getTextColour(int mousex, int mousey) { public int getTextColour(int mousex, int mousey) {
return !isEnabled ? ColorUtils.buttonTextDisabled.getColor() return !isEnabled ? LocalizedColours.BUTTON_TEXT_DISABLED
: pointInside(mousex, mousey) ? ColorUtils.buttonTextHover.getColor() : pointInside(mousex, mousey) ? LocalizedColours.BUTTON_TEXT_HOVER : LocalizedColours.BUTTON_TEXT;
: ColorUtils.buttonText.getColor();
} }
public GuiCCButton setActionCommand(String string) { public GuiCCButton setActionCommand(String string) {
@@ -5,7 +5,7 @@ import net.minecraft.util.ChatAllowedCharacters;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import codechicken.lib.colour.ColorUtils; import codechicken.lib.colour.LocalizedColours;
public class GuiCCTextField extends GuiWidget { public class GuiCCTextField extends GuiWidget {
@@ -122,8 +122,8 @@ public class GuiCCTextField extends GuiWidget {
} }
public void drawBackground() { public void drawBackground() {
drawRect(x - 1, y - 1, x + width + 1, y + height + 1, ColorUtils.textFieldBorder.getColor()); drawRect(x - 1, y - 1, x + width + 1, y + height + 1, LocalizedColours.TEXT_FIELD_BORDER);
drawRect(x, y, x + width, y + height, ColorUtils.textFieldBackground.getColor()); drawRect(x, y, x + width, y + height, LocalizedColours.TEXT_FIELD_BACKGROUND);
} }
public String getDrawText() { public String getDrawText() {
@@ -137,7 +137,7 @@ public class GuiCCTextField extends GuiWidget {
} }
public int getTextColour() { public int getTextColour() {
return isEnabled ? ColorUtils.textFieldText.getColor() : ColorUtils.textFieldTextDisabled.getColor(); return isEnabled ? LocalizedColours.TEXT_FIELD_TEXT : LocalizedColours.TEXT_FIELD_TEXT_DISABLED;
} }
public GuiCCTextField setMaxStringLength(int i) { public GuiCCTextField setMaxStringLength(int i) {
@@ -3,7 +3,7 @@ package codechicken.core.gui;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Rectangle; import java.awt.Rectangle;
import codechicken.lib.colour.ColorUtils; import codechicken.lib.colour.LocalizedColours;
import codechicken.lib.math.MathHelper; import codechicken.lib.math.MathHelper;
import codechicken.lib.vec.Rectangle4i; import codechicken.lib.vec.Rectangle4i;
@@ -185,29 +185,29 @@ public abstract class GuiScrollPane extends GuiWidget {
} }
public void drawBackground(float frame) { public void drawBackground(float frame) {
drawRect(x, y, x + width, y + height, ColorUtils.scrollPaneBackground.getColor()); drawRect(x, y, x + width, y + height, LocalizedColours.SCROLL_PANE_BACKGROUND);
} }
public abstract void drawContent(int mx, int my, float frame); public abstract void drawContent(int mx, int my, float frame);
public void drawOverlay(float frame) { public void drawOverlay(float frame) {
// outlines // outlines
drawRect(x, y - 1, x + width, y, ColorUtils.scrollPaneOverlayTop.getColor()); drawRect(x, y - 1, x + width, y, LocalizedColours.SCROLL_PANE_OVERLAY_TOP);
drawRect(x, y + height, x + width, y + height + 1, ColorUtils.scrollPaneOverlayBottom.getColor()); drawRect(x, y + height, x + width, y + height + 1, LocalizedColours.SCROLL_PANE_OVERLAY_BOTTOM);
drawRect(x - 1, y - 1, x, y + height + 1, ColorUtils.scrollPaneOverlayLeft.getColor()); drawRect(x - 1, y - 1, x, y + height + 1, LocalizedColours.SCROLL_PANE_OVERLAY_LEFT);
drawRect(x + width, y - 1, x + width + 1, y + height + 1, ColorUtils.scrollPaneOverlayRight.getColor()); drawRect(x + width, y - 1, x + width + 1, y + height + 1, LocalizedColours.SCROLL_PANE_OVERLAY_RIGHT);
} }
public void drawScrollbar(float frame) { public void drawScrollbar(float frame) {
Rectangle r = scrollbarBounds(); Rectangle r = scrollbarBounds();
drawRect(r.x, r.y, r.x + r.width, r.y + r.height, ColorUtils.scrollbarCorners.getColor()); drawRect(r.x, r.y, r.x + r.width, r.y + r.height, LocalizedColours.SCROLLBAR_CORNERS);
drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, ColorUtils.scrollbarTopLeft.getColor()); drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, LocalizedColours.SCROLLBAR_TOP_LEFT);
drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, ColorUtils.scrollbarBottomRight.getColor()); drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, LocalizedColours.SCROLLBAR_BOTTOM_RIGHT);
drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, ColorUtils.scrollbarFill.getColor()); drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, LocalizedColours.SCROLLBAR_FILL);
int algn = scrollbarGuideAlignment(); int algn = scrollbarGuideAlignment();
if (algn != 0) if (algn != 0)
drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, ColorUtils.scrollbarGuide.getColor()); drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, LocalizedColours.SCROLLBAR_GUIDE);
} }
} }
@@ -1,38 +0,0 @@
package codechicken.lib.colour;
import com.gtnewhorizon.gtnhlib.color.ColorResource;
public class ColorUtils {
private static final ColorResource.Factory color = new ColorResource.Factory("codechickencore");
public static final ColorResource
// spotless:off
textFieldText = color.rgb("textFieldText", "0xE0E0E0"),
textFieldTextDisabled = color.rgb("textFieldTextDisabled", "0x707070"),
itemQuantityText = color.rgb("itemQuantityText", "0xFFFFFF"),
modDescriptionText = color.rgb("modDescriptionText", "0xDDDDDD"),
buttonTextDisabled = color.argb("buttonTextDisabled", "0xFFA0A0A0"),
buttonTextHover = color.argb("buttonTextHover", "0xFFFFFFA0"),
buttonText = color.argb("buttonText", "0xFFE0E0E0"),
textFieldBorder = color.argb("textFieldBorder", "0xFFA0A0A0"),
textFieldBackground = color.argb("textFieldBackground", "0xFF000000"),
scrollPaneBackground = color.argb("background", "0xFF000000"),
scrollPaneOverlayTop = color.argb("overlayTop", "0xFFA0A0A0"),
scrollPaneOverlayBottom = color.argb("overlayBottom", "0xFFA0A0A0"),
scrollPaneOverlayLeft = color.argb("overlayLeft", "0xFFA0A0A0"),
scrollPaneOverlayRight = color.argb("overlayRight", "0xFFA0A0A0"),
scrollbarCorners = color.argb("scrollbarCorners", "0xFF8B8B8B"),
scrollbarTopLeft = color.argb("scrollbarTopLeft", "0xFFF0F0F0"),
scrollbarBottomRight = color.argb("scrollbarBottomRight", "0xFF555555"),
scrollbarFill = color.argb("scrollbarFill", "0xFFC6C6C6"),
scrollbarGuide = color.argb("scrollbarGuide", "0xFF808080"),
tooltipBgStart = color.argb("tooltipBgStart", "0xF0100010"),
tooltipBgEnd = color.argb("tooltipBgEnd", "0xF0100010"),
tooltipBorderStart = color.argb("tooltipBorderStart", "0x505000FF"),
tooltipBorderEnd = color.argb("tooltipBorderEnd", "0x5028007F"),
tooltipText = color.argb("tooltipText", "0xFFFFFFFF");
// spotless:on
}
@@ -0,0 +1,86 @@
package codechicken.lib.colour;
import net.minecraft.util.StatCollector;
public final class LocalizedColours {
private static final String KEY_PREFIX = "codechickencore.color.";
public static int BUTTON_TEXT_DISABLED = 0xFFA0A0A0;
public static int BUTTON_TEXT_HOVER = 0xFFFFFFA0;
public static int BUTTON_TEXT = 0xFFE0E0E0;
public static int TEXT_FIELD_BORDER = 0xFFA0A0A0;
public static int TEXT_FIELD_BACKGROUND = 0xFF000000;
public static int TEXT_FIELD_TEXT = 0xE0E0E0;
public static int TEXT_FIELD_TEXT_DISABLED = 0x707070;
public static int SCROLL_PANE_BACKGROUND = 0xFF000000;
public static int SCROLL_PANE_OVERLAY_TOP = 0xFFA0A0A0;
public static int SCROLL_PANE_OVERLAY_BOTTOM = 0xFFA0A0A0;
public static int SCROLL_PANE_OVERLAY_LEFT = 0xFFA0A0A0;
public static int SCROLL_PANE_OVERLAY_RIGHT = 0xFFA0A0A0;
public static int SCROLLBAR_CORNERS = 0xFF8B8B8B;
public static int SCROLLBAR_TOP_LEFT = 0xFFF0F0F0;
public static int SCROLLBAR_BOTTOM_RIGHT = 0xFF555555;
public static int SCROLLBAR_FILL = 0xFFC6C6C6;
public static int SCROLLBAR_GUIDE = 0xFF808080;
public static int TOOLTIP_BG_START = 0xF0100010;
public static int TOOLTIP_BG_END = 0xF0100010;
public static int TOOLTIP_BORDER_START = 0x505000FF;
public static int TOOLTIP_BORDER_END = 0x5028007F;
public static int TOOLTIP_TEXT = 0xFFFFFFFF;
public static int ITEM_QUANTITY_TEXT = 0xFFFFFF;
public static int MOD_DESCRIPTION_TEXT = 0xDDDDDD;
private LocalizedColours() {}
public static void reloadLocalizedColours() {
BUTTON_TEXT_DISABLED = getLocalizedColor("buttonTextDisabled", BUTTON_TEXT_DISABLED);
BUTTON_TEXT_HOVER = getLocalizedColor("buttonTextHover", BUTTON_TEXT_HOVER);
BUTTON_TEXT = getLocalizedColor("buttonText", BUTTON_TEXT);
TEXT_FIELD_BORDER = getLocalizedColor("textFieldBorder", TEXT_FIELD_BORDER);
TEXT_FIELD_BACKGROUND = getLocalizedColor("textFieldBackground", TEXT_FIELD_BACKGROUND);
TEXT_FIELD_TEXT = getLocalizedColor("textFieldText", TEXT_FIELD_TEXT);
TEXT_FIELD_TEXT_DISABLED = getLocalizedColor("textFieldTextDisabled", TEXT_FIELD_TEXT_DISABLED);
SCROLL_PANE_BACKGROUND = getLocalizedColor("background", SCROLL_PANE_BACKGROUND);
SCROLL_PANE_OVERLAY_TOP = getLocalizedColor("overlayTop", SCROLL_PANE_OVERLAY_TOP);
SCROLL_PANE_OVERLAY_BOTTOM = getLocalizedColor("overlayBottom", SCROLL_PANE_OVERLAY_BOTTOM);
SCROLL_PANE_OVERLAY_LEFT = getLocalizedColor("overlayLeft", SCROLL_PANE_OVERLAY_LEFT);
SCROLL_PANE_OVERLAY_RIGHT = getLocalizedColor("overlayRight", SCROLL_PANE_OVERLAY_RIGHT);
SCROLLBAR_CORNERS = getLocalizedColor("scrollbarCorners", SCROLLBAR_CORNERS);
SCROLLBAR_TOP_LEFT = getLocalizedColor("scrollbarTopLeft", SCROLLBAR_TOP_LEFT);
SCROLLBAR_BOTTOM_RIGHT = getLocalizedColor("scrollbarBottomRight", SCROLLBAR_BOTTOM_RIGHT);
SCROLLBAR_FILL = getLocalizedColor("scrollbarFill", SCROLLBAR_FILL);
SCROLLBAR_GUIDE = getLocalizedColor("scrollbarGuide", SCROLLBAR_GUIDE);
TOOLTIP_BG_START = getLocalizedColor("tooltipBgStart", TOOLTIP_BG_START);
TOOLTIP_BG_END = getLocalizedColor("tooltipBgEnd", TOOLTIP_BG_END);
TOOLTIP_BORDER_START = getLocalizedColor("tooltipBorderStart", TOOLTIP_BORDER_START);
TOOLTIP_BORDER_END = getLocalizedColor("tooltipBorderEnd", TOOLTIP_BORDER_END);
TOOLTIP_TEXT = getLocalizedColor("tooltipText", TOOLTIP_TEXT);
ITEM_QUANTITY_TEXT = getLocalizedColor("itemQuantityText", ITEM_QUANTITY_TEXT);
MOD_DESCRIPTION_TEXT = getLocalizedColor("modDescriptionText", MOD_DESCRIPTION_TEXT);
}
/**
* Resolve a optional localized ARGB color from lang files. Expected value format: AARRGGBB (for example FF555555).
*/
private static int getLocalizedColor(String key, int defaultColor) {
String fullKey = KEY_PREFIX + key;
if (!StatCollector.canTranslate(fullKey)) {
return defaultColor;
}
String raw = StatCollector.translateToLocal(fullKey);
String hex = raw.trim();
if (hex.startsWith("0x") || hex.startsWith("0X")) {
hex = hex.substring(2);
} else if (hex.startsWith("#")) {
hex = hex.substring(1);
}
try {
return (int) Long.parseLong(hex, 16);
} catch (NumberFormatException ignored) {
return defaultColor;
}
}
}
+10 -10
View File
@@ -18,7 +18,7 @@ import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12; import org.lwjgl.opengl.GL12;
import codechicken.lib.colour.ColorUtils; import codechicken.lib.colour.LocalizedColours;
import codechicken.lib.math.MathHelper; import codechicken.lib.math.MathHelper;
import codechicken.lib.render.CCRenderState; import codechicken.lib.render.CCRenderState;
@@ -168,10 +168,10 @@ public class GuiDraw {
x, x,
y, y,
list, list,
ColorUtils.tooltipBgStart.getColor(), LocalizedColours.TOOLTIP_BG_START,
ColorUtils.tooltipBgEnd.getColor(), LocalizedColours.TOOLTIP_BG_END,
ColorUtils.tooltipBorderStart.getColor(), LocalizedColours.TOOLTIP_BORDER_START,
ColorUtils.tooltipBorderEnd.getColor()); LocalizedColours.TOOLTIP_BORDER_END);
} }
public static void drawMultilineTip(FontRenderer font, int x, int y, List<String> list, int bgStart, int bgEnd, public static void drawMultilineTip(FontRenderer font, int x, int y, List<String> list, int bgStart, int bgEnd,
@@ -210,7 +210,7 @@ public class GuiDraw {
line.draw(x, y); line.draw(x, y);
y += line.getSize().height; y += line.getSize().height;
} else { } else {
font.drawStringWithShadow(s, x, y, ColorUtils.tooltipText.getColor()); font.drawStringWithShadow(s, x, y, LocalizedColours.TOOLTIP_TEXT);
y += s.endsWith(TOOLTIP_LINESPACE) ? 12 : 10; y += s.endsWith(TOOLTIP_LINESPACE) ? 12 : 10;
} }
} }
@@ -229,10 +229,10 @@ public class GuiDraw {
y, y,
w, w,
h, h,
ColorUtils.tooltipBgStart.getColor(), LocalizedColours.TOOLTIP_BG_START,
ColorUtils.tooltipBgEnd.getColor(), LocalizedColours.TOOLTIP_BG_END,
ColorUtils.tooltipBorderStart.getColor(), LocalizedColours.TOOLTIP_BORDER_START,
ColorUtils.tooltipBorderEnd.getColor()); LocalizedColours.TOOLTIP_BORDER_END);
} }
public static void drawTooltipBox(int x, int y, int w, int h, int bgStart, int bgEnd, int borderStart, public static void drawTooltipBox(int x, int y, int w, int h, int bgStart, int bgEnd, int borderStart,
@@ -12,7 +12,12 @@ import codechicken.lib.vec.BlockCoord;
public class SimpleBrightnessModel implements CCRenderState.IVertexOperation { public class SimpleBrightnessModel implements CCRenderState.IVertexOperation {
public static final int operationIndex = CCRenderState.registerOperation(); public static final int operationIndex = CCRenderState.registerOperation();
public static SimpleBrightnessModel instance = new SimpleBrightnessModel(); private static final ThreadLocal<SimpleBrightnessModel> instances = ThreadLocal
.withInitial(SimpleBrightnessModel::new);
public static SimpleBrightnessModel instance() {
return instances.get();
}
public IBlockAccess access; public IBlockAccess access;
public BlockCoord pos = new BlockCoord(); public BlockCoord pos = new BlockCoord();
@@ -466,7 +466,7 @@ public final class PacketCustom implements MCDataInput, MCDataOutput {
public FluidStack readFluidStack() { public FluidStack readFluidStack() {
Fluid fluid = FluidRegistry.getFluid(readShort()); Fluid fluid = FluidRegistry.getFluid(readShort());
if (fluid == null) fluid = FluidRegistry.WATER; if (fluid == null) return null;
return new FluidStack(fluid, readVarInt(), readNBTTagCompound()); return new FluidStack(fluid, readVarInt(), readNBTTagCompound());
} }
@@ -1,6 +1,7 @@
package codechicken.lib.render; package codechicken.lib.render;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.OpenGlHelper;
@@ -38,9 +39,9 @@ public class CCRenderState {
return instances.get(); return instances.get();
} }
private static int nextOperationIndex; private static volatile int nextOperationIndex;
public static int registerOperation() { public static synchronized int registerOperation() {
return nextOperationIndex++; return nextOperationIndex++;
} }
@@ -87,15 +88,52 @@ public class CCRenderState {
int operationID(); int operationID();
} }
private static ArrayList<VertexAttribute<?>> vertexAttributes = new ArrayList<>(); public static final class AttributeKey<T> {
private static int registerVertexAttribute(VertexAttribute<?> attr) { private static final HashMap<String, AttributeKey<?>> nameMap = new HashMap<>();
vertexAttributes.add(attr); private static final ArrayList<AttributeKey<?>> attributeKeys = new ArrayList<>();
return vertexAttributes.size() - 1; private static int nextLegacyId;
public final String name;
public final int attributeKeyIndex;
public final int operationIndex;
private VertexAttribute<T> canonical;
private AttributeKey(String name) {
this.name = name;
this.attributeKeyIndex = attributeKeys.size();
this.operationIndex = registerOperation();
attributeKeys.add(this);
nameMap.put(name, this);
}
public static synchronized <T> AttributeKey<T> create(String name) {
if (nameMap.containsKey(name))
throw new IllegalArgumentException("Duplicate registration of attribute with name: " + name);
return new AttributeKey<>(name);
}
static synchronized <T> AttributeKey<T> createLegacy() {
return new AttributeKey<>("legacy#" + nextLegacyId++);
}
synchronized void setCanonical(VertexAttribute<T> attr) {
if (canonical == null) canonical = attr;
}
static synchronized AttributeKey<?> get(int index) {
return attributeKeys.get(index);
}
} }
private static final AttributeKey<Vector3[]> NORMAL_KEY = AttributeKey.create("normal");
private static final AttributeKey<int[]> COLOUR_KEY = AttributeKey.create("colour");
private static final AttributeKey<int[]> LIGHTING_KEY = AttributeKey.create("lighting");
private static final AttributeKey<int[]> SIDE_KEY = AttributeKey.create("side");
private static final AttributeKey<LC[]> LC_KEY = AttributeKey.create("lc");
public static VertexAttribute<?> getAttribute(int index) { public static VertexAttribute<?> getAttribute(int index) {
return vertexAttributes.get(index); return AttributeKey.get(index).canonical;
} }
/** /**
@@ -106,14 +144,26 @@ public class CCRenderState {
*/ */
public abstract static class VertexAttribute<T> implements IVertexOperation { public abstract static class VertexAttribute<T> implements IVertexOperation {
public final int attributeIndex = registerVertexAttribute(this); public final int attributeIndex;
private final int operationIndex = registerOperation(); private final int operationIndex;
/** /**
* Set to true when the attrute is part of the pipeline. Should only be managed by CCRenderState when * Set to true when the attrute is part of the pipeline. Should only be managed by CCRenderState when
* constructing the pipeline * constructing the pipeline
*/ */
public boolean active = false; public boolean active = false;
protected VertexAttribute(AttributeKey<T> key) {
attributeIndex = key.attributeKeyIndex;
operationIndex = key.operationIndex;
key.setCanonical(this);
}
/** @deprecated keyless attributes get a per-construction index that is threadsafe */
@Deprecated
protected VertexAttribute() {
this(AttributeKey.createLegacy());
}
/** /**
* Construct a new array for storage of vertex attrutes in a model * Construct a new array for storage of vertex attrutes in a model
*/ */
@@ -189,7 +239,7 @@ public class CCRenderState {
return instances.get().lightingAttrib; return instances.get().lightingAttrib;
} }
public VertexAttribute<Vector3[]> normalAttrib = new VertexAttribute<>() { public VertexAttribute<Vector3[]> normalAttrib = new VertexAttribute<>(NORMAL_KEY) {
private Vector3[] normalRef; private Vector3[] normalRef;
@@ -217,7 +267,7 @@ public class CCRenderState {
else state.setNormalInstance(Rotation.axes[state.side]); else state.setNormalInstance(Rotation.axes[state.side]);
} }
}; };
public VertexAttribute<int[]> colourAttrib = new VertexAttribute<>() { public VertexAttribute<int[]> colourAttrib = new VertexAttribute<>(COLOUR_KEY) {
private int[] colourRef; private int[] colourRef;
@@ -239,7 +289,7 @@ public class CCRenderState {
else state.setColourInstance(state.baseColour); else state.setColourInstance(state.baseColour);
} }
}; };
public VertexAttribute<int[]> lightingAttrib = new VertexAttribute<>() { public VertexAttribute<int[]> lightingAttrib = new VertexAttribute<>(LIGHTING_KEY) {
private int[] colourRef; private int[] colourRef;
@@ -265,7 +315,7 @@ public class CCRenderState {
state.setColourInstance(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex])); state.setColourInstance(ColourRGBA.multiply(state.colour, colourRef[state.vertexIndex]));
} }
}; };
public VertexAttribute<int[]> sideAttrib = new VertexAttribute<>() { public VertexAttribute<int[]> sideAttrib = new VertexAttribute<>(SIDE_KEY) {
private int[] sideRef; private int[] sideRef;
@@ -292,7 +342,7 @@ public class CCRenderState {
/** /**
* Uses the position of the lightmatrix to compute LC if not provided * Uses the position of the lightmatrix to compute LC if not provided
*/ */
public VertexAttribute<LC[]> lightCoordAttrib = new VertexAttribute<>() { public VertexAttribute<LC[]> lightCoordAttrib = new VertexAttribute<>(LC_KEY) {
private LC[] lcRef; private LC[] lcRef;
private final Vector3 vec = new Vector3(); // for computation private final Vector3 vec = new Vector3(); // for computation
@@ -1,5 +1,7 @@
package codechicken.lib.render; package codechicken.lib.render;
import java.util.Arrays;
import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityFX; import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
@@ -11,6 +13,9 @@ import codechicken.lib.vec.Vector3;
public class EntityDigIconFX extends EntityFX { public class EntityDigIconFX extends EntityFX {
/** Tint that leaves the particle colour untouched, for materials that don't colour their texture. */
public static final int NO_TINT = 0xFFFFFF;
public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) { public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) {
super(world, x, y, z, dx, dy, dz); super(world, x, y, z, dx, dy, dz);
particleIcon = icon; particleIcon = icon;
@@ -19,6 +24,18 @@ public class EntityDigIconFX extends EntityFX {
particleScale /= 2.0F; particleScale /= 2.0F;
} }
/**
* Multiplies the particle colour by an 0xRRGGBB tint, the equivalent of vanilla
* EntityDiggingFX.applyColourMultiplier. Materials that draw a greyscale texture and colour it at render time
* (leaves, grass tops) need this, or their particles come out flat grey.
*/
public EntityDigIconFX applyColourMultiplier(int colour) {
particleRed *= (colour >> 16 & 255) / 255F;
particleGreen *= (colour >> 8 & 255) / 255F;
particleBlue *= (colour & 255) / 255F;
return this;
}
@Override @Override
public int getFXLayer() { public int getFXLayer() {
return 1; return 1;
@@ -90,8 +107,24 @@ public class EntityDigIconFX extends EntityFX {
f9); f9);
} }
/**
* @deprecated the particle is never tinted, so a material that colours a greyscale texture at render time (leaves,
* grass tops) breaks into grey particles. Use
* {@link #addBlockHitEffects(World, Cuboid6, int, IIcon, int, EffectRenderer)}, passing
* {@link #NO_TINT} for materials whose texture is already coloured.
*/
@Deprecated
public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon, public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon,
EffectRenderer effectRenderer) { EffectRenderer effectRenderer) {
addBlockHitEffects(world, bounds, side, icon, NO_TINT, effectRenderer);
}
/**
* Spawns a hit particle on side of bounds, tinted by colour (0xRRGGBB, {@link #NO_TINT} for none). The caller
* resolves the tint for the side it hit, so per-face materials like grass can tint only the faces that need it.
*/
public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon, int colour,
EffectRenderer effectRenderer) {
float border = 0.1F; float border = 0.1F;
Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2 * border); Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2 * border);
diff.x *= world.rand.nextDouble(); diff.x *= world.rand.nextDouble();
@@ -106,13 +139,34 @@ public class EntityDigIconFX extends EntityFX {
if (side == 4) diff.x = bounds.min.x - border; if (side == 4) diff.x = bounds.min.x - border;
if (side == 5) diff.x = bounds.max.x + border; if (side == 5) diff.x = bounds.max.x + border;
effectRenderer.addEffect( EntityDigIconFX fx = new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon);
new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon).multiplyVelocity(0.2F) effectRenderer.addEffect(fx.applyColourMultiplier(colour).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F));
.multipleParticleScaleBy(0.6F));
} }
/**
* @deprecated the particles are never tinted, so a material that colours a greyscale texture at render time
* (leaves, grass tops) breaks into grey particles. Use
* {@link #addBlockDestroyEffects(World, Cuboid6, IIcon[], int[], EffectRenderer)}, passing
* {@link #NO_TINT} for the faces whose texture is already coloured.
*/
@Deprecated
public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons, public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons,
EffectRenderer effectRenderer) { EffectRenderer effectRenderer) {
int[] colours = new int[icons.length];
Arrays.fill(colours, NO_TINT);
addBlockDestroyEffects(world, bounds, icons, colours, effectRenderer);
}
/**
* Spawns break particles filling bounds, each drawn from a random face. colours holds the 0xRRGGBB tint for the
* matching entry of icons ({@link #NO_TINT} for none) and must be the same length, so a particle is tinted by the
* face it was taken from.
*/
public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons, int[] colours,
EffectRenderer effectRenderer) {
if (icons.length != colours.length)
throw new IllegalArgumentException("icons and colours must have the same length");
Vector3 diff = bounds.max.copy().subtract(bounds.min); Vector3 diff = bounds.max.copy().subtract(bounds.min);
Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5); Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5);
Vector3 density = diff.copy().multiply(4); Vector3 density = diff.copy().multiply(4);
@@ -121,19 +175,20 @@ public class EntityDigIconFX extends EntityFX {
density.z = Math.ceil(density.z); density.z = Math.ceil(density.z);
for (int i = 0; i < density.x; ++i) for (int j = 0; j < density.y; ++j) for (int k = 0; k < density.z; ++k) { for (int i = 0; i < density.x; ++i) for (int j = 0; j < density.y; ++j) for (int k = 0; k < density.z; ++k) {
double x = bounds.min.x + (i + 0.5) * diff.x / density.x; double px = bounds.min.x + (i + 0.5) * diff.x / density.x;
double y = bounds.min.y + (j + 0.5) * diff.y / density.y; double py = bounds.min.y + (j + 0.5) * diff.y / density.y;
double z = bounds.min.z + (k + 0.5) * diff.z / density.z; double pz = bounds.min.z + (k + 0.5) * diff.z / density.z;
effectRenderer.addEffect( int iconSide = world.rand.nextInt(icons.length);
new EntityDigIconFX( EntityDigIconFX fx = new EntityDigIconFX(
world, world,
x, px,
y, py,
z, pz,
x - center.x, px - center.x,
y - center.y, py - center.y,
z - center.z, pz - center.z,
icons[world.rand.nextInt(icons.length)])); icons[iconSide]);
effectRenderer.addEffect(fx.applyColourMultiplier(colours[iconSide]));
} }
} }
} }
@@ -6,7 +6,7 @@ import net.minecraft.item.ItemStack;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import codechicken.lib.colour.ColorUtils; import codechicken.lib.colour.LocalizedColours;
public class FontUtils { public class FontUtils {
@@ -55,7 +55,7 @@ public class FontUtils {
GL11.glPushMatrix(); GL11.glPushMatrix();
GL11.glTranslated(x + 16 - swidth, y + 16 - sheight, 0); GL11.glTranslated(x + 16 - swidth, y + 16 - sheight, 0);
GL11.glScaled(scale, scale, 1); GL11.glScaled(scale, scale, 1);
fontRenderer.drawStringWithShadow(quantity, 0, 0, ColorUtils.itemQuantityText.getColor()); fontRenderer.drawStringWithShadow(quantity, 0, 0, LocalizedColours.ITEM_QUANTITY_TEXT);
GL11.glPopMatrix(); GL11.glPopMatrix();
GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_DEPTH_TEST);
@@ -55,7 +55,10 @@ public class WorldExtensionManager {
public void onChunkUnLoad(ChunkEvent.Unload event) { public void onChunkUnLoad(ChunkEvent.Unload event) {
if (event.getChunk() instanceof EmptyChunk) return; if (event.getChunk() instanceof EmptyChunk) return;
for (WorldExtension extension : worldMap.get(event.world)) extension.unloadChunk(event.getChunk()); WorldExtension[] extensions = worldMap.get(event.world);
if (extensions == null) return;
for (WorldExtension extension : extensions) extension.unloadChunk(event.getChunk());
if (event.world.isRemote) removeChunk(event.world, event.getChunk()); if (event.world.isRemote) removeChunk(event.world, event.getChunk());
} }
@@ -1 +1,26 @@
codechickencore.update=Version %s of %s is available codechickencore.update=Version %s of %s is available
codechickencore.color.buttonTextDisabled=FFA0A0A0
codechickencore.color.buttonTextHover=FFFFFFA0
codechickencore.color.buttonText=FFE0E0E0
codechickencore.color.textFieldBorder=FFA0A0A0
codechickencore.color.textFieldBackground=FF000000
codechickencore.color.textFieldText=E0E0E0
codechickencore.color.textFieldTextDisabled=707070
codechickencore.color.background=FF000000
codechickencore.color.overlayTop=FFA0A0A0
codechickencore.color.overlayBottom=FFA0A0A0
codechickencore.color.overlayLeft=FFA0A0A0
codechickencore.color.overlayRight=FFA0A0A0
codechickencore.color.scrollbarCorners=FF8B8B8B
codechickencore.color.scrollbarTopLeft=FFF0F0F0
codechickencore.color.scrollbarBottomRight=FF555555
codechickencore.color.scrollbarFill=FFC6C6C6
codechickencore.color.scrollbarGuide=FF808080
codechickencore.color.tooltipBgStart=F0100010
codechickencore.color.tooltipBgEnd=F0100010
codechickencore.color.tooltipBorderStart=505000FF
codechickencore.color.tooltipBorderEnd=5028007F
codechickencore.color.tooltipText=FFFFFFFF
codechickencore.color.itemQuantityText=FFFFFF
codechickencore.color.modDescriptionText=DDDDDD
@@ -0,0 +1 @@
codechickencore.update=Доступна версія %s для %s
@@ -0,0 +1,102 @@
package codechicken.lib.render;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import codechicken.lib.vec.Vector3;
public class CCRenderStateThreadingTest {
private static int[] attribIndices() {
return new int[] { CCRenderState.normalAttrib().attributeIndex, CCRenderState.colourAttrib().attributeIndex,
CCRenderState.lightingAttrib().attributeIndex, CCRenderState.sideAttrib().attributeIndex,
CCRenderState.lightCoordAttrib().attributeIndex };
}
@Test
public void attributeIndicesStableAcrossThreads() throws Exception {
int[] main = attribIndices();
assertEquals(5, Arrays.stream(main).distinct().count());
ExecutorService pool = Executors.newFixedThreadPool(8);
try {
List<Future<int[]>> futures = new ArrayList<>();
for (int i = 0; i < 8; i++) futures.add(pool.submit(CCRenderStateThreadingTest::attribIndices));
for (Future<int[]> f : futures) assertArrayEquals(main, f.get(10, TimeUnit.SECONDS));
} finally {
pool.shutdownNow();
}
}
@Test
public void modelBakedOnOneThreadIsReadableOnAnother() throws Exception {
ExecutorService bakeThread = Executors.newSingleThreadExecutor();
ExecutorService renderThread = Executors.newSingleThreadExecutor();
try {
CCModel model = bakeThread.submit(() -> {
CCModel m = CCModel.quadModel(4);
m.verts[0] = new Vertex5(0, 1, 0, 0, 0);
m.verts[1] = new Vertex5(0, 1, 1, 0, 1);
m.verts[2] = new Vertex5(1, 1, 1, 1, 1);
m.verts[3] = new Vertex5(1, 1, 0, 1, 0);
return m.computeNormals();
}).get(10, TimeUnit.SECONDS);
int side = renderThread.submit(() -> {
assertTrue(
model.hasAttribute(CCRenderState.normalAttrib()),
"normals baked on another thread not visible under this thread's attributeIndex");
Vector3[] normals = model.getAttributes(CCRenderState.normalAttrib());
assertNotNull(normals);
return CCModel.findSide(normals[0]);
}).get(10, TimeUnit.SECONDS);
assertEquals(1, side);
assertEquals(1, CCModel.findSide(model.getAttributes(CCRenderState.normalAttrib())[0]));
} finally {
bakeThread.shutdownNow();
renderThread.shutdownNow();
}
}
@Test
public void concurrentFirstUseKeepsIndicesConsistent() throws Exception {
int threads = 16;
CyclicBarrier barrier = new CyclicBarrier(threads);
ExecutorService pool = Executors.newFixedThreadPool(threads);
try {
List<Future<int[]>> futures = new ArrayList<>();
for (int i = 0; i < threads; i++) futures.add(pool.submit(() -> {
barrier.await(10, TimeUnit.SECONDS);
return attribIndices();
}));
int[] expected = attribIndices();
for (Future<int[]> f : futures) assertArrayEquals(expected, f.get(10, TimeUnit.SECONDS));
} finally {
pool.shutdownNow();
}
}
@Test
public void getAttributeReturnsCanonicalForIndex() {
int normalIndex = CCRenderState.normalAttrib().attributeIndex;
CCRenderState.VertexAttribute<?> canonical = CCRenderState.getAttribute(normalIndex);
assertNotNull(canonical);
assertEquals(normalIndex, canonical.attributeIndex);
assertSame(canonical, CCRenderState.getAttribute(normalIndex));
}
}
@@ -0,0 +1,20 @@
package codechicken.lib.render;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import net.minecraft.util.IIcon;
import org.junit.jupiter.api.Test;
public class EntityDigIconFXTest {
@Test
public void rejectsMismatchedIconAndColourCountsBeforeSpawning() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> EntityDigIconFX.addBlockDestroyEffects(null, null, new IIcon[1], new int[0], null));
assertEquals("icons and colours must have the same length", exception.getMessage());
}
}