feat(onlyfun): feux d'artifice ChrisM, Duncan et autres visages #176

Merged
koka merged 1 commits from feature/skin-fireworks into main 2026-09-10 12:24:00 +00:00
53 changed files with 870 additions and 76 deletions
+48 -32
View File
@@ -3916,11 +3916,15 @@ project(":onlyfun") {
"src/main/java/fr/koka99cab/sanctuary26/onlyfun/world/CobbleDungeonStructure.java").text
def dungeonStructureSet = new JsonSlurper().parse(file(
"src/main/resources/data/onlyfun/worldgen/structure_set/cobble_dungeons.json"))
def expectedItems = ["normal_lootbox", "cape_lootbox", "spawn_egg_lootbox", "anomaly_lootbox", "lucky_block", "nourra_firework"]
def fireworkIds = ["nourra", "chrism", "kaninscheun", "poupoutain", "lbeast",
"creveforest", "sacdchips", "vaselline", "duncan"]
def expectedItems = ["normal_lootbox", "cape_lootbox", "spawn_egg_lootbox", "anomaly_lootbox", "lucky_block"] +
fireworkIds.collect { "${it}_firework" }
def missingModels = expectedItems.findAll { id ->
!file("src/main/resources/assets/onlyfun/items/${id}.json").exists()
}
def textureIds = ["normal_lootbox", "cape_lootbox", "spawn_egg_lootbox", "anomaly_lootbox", "nourra_firework"]
def textureIds = ["normal_lootbox", "cape_lootbox", "spawn_egg_lootbox", "anomaly_lootbox"] +
fireworkIds.collect { "${it}_firework" }
def invalidTextures = textureIds.findAll { id ->
def texture = file("src/main/resources/assets/onlyfun/textures/item/${id}.png")
if (!texture.isFile()) return true
@@ -4138,41 +4142,53 @@ project(":onlyfun") {
|| !shopCsvText.contains("TRUE,ITEM,iliketomoveit:magic_cloud,1,3072,192,")
|| !javaText.contains("MAGIC_CLOUD, MAGIC_CARPET")
|| !file("src/main/resources/assets/onlyfun/models/block/lucky_block.json").text.contains("onlyfun:block/lucky_block")
|| !javaText.contains("class NourraFireworkItem extends FireworkRocketItem")
|| !javaText.contains("class SkinFaceFireworkExplosions")
|| !javaText.contains("FACE = {")
|| !javaText.contains("HOOD = {")
|| !javaText.contains("HOOD_TOP = {")
|| !javaText.contains("0x4A9DFC")
|| !javaText.contains("TRANSPARENT")
|| !javaText.contains("class SkinFaceFireworkClient")
|| !javaText.contains("DustParticleOptions")
|| !javaText.contains("PIXEL = 1.85D")
|| !javaText.contains("LARGE_PIXEL = 2.7D")
|| !javaText.contains("LARGE_SPARK_SIZE = 5.15F")
|| !javaText.contains("SPARK_LIFETIME_TICKS = 38")
|| !javaText.contains("new Fireworks(3, List.of())")
|| !javaText.contains("LIFETIME_TRIM_TICKS = 5")
|| !javaText.contains("onlyfun\$midFlightLifetime")
|| !javaText.contains("onlyfun\$drawSkinFace")
|| !javaText.contains("output.accept(OnlyFunRegistries.NOURRA_FIREWORK)")
|| !file("src/main/resources/onlyfun.mixins.json").text.contains("FireworkRocketLifetimeMixin")
|| !file("src/main/resources/onlyfun.client.mixins.json").text.contains("FireworkRocketEntityMixin")
|| !file("src/main/resources/onlyfun.client.mixins.json").text.contains("ParticleLifetimeAccessor")
|| !file("src/main/resources/fabric.mod.json").text.contains("onlyfun.mixins.json")
|| !file("src/main/resources/fabric.mod.json").text.contains("onlyfun.client.mixins.json")
|| !file("src/main/resources/data/onlyfun/recipe/nourra_firework.json").text.contains("onlyfun:nourra_firework")
|| ["fr_fr", "en_us", "ru_ru"].any { locale ->
def translations = new JsonSlurper().parse(file(
"src/main/resources/assets/onlyfun/lang/${locale}.json"))
!translations.containsKey("item.onlyfun.nourra_firework")
|| !translations.containsKey("tooltip.onlyfun.nourra_firework")
}
|| !missingModels.isEmpty()
|| !invalidTextureHashes.isEmpty()
|| !invalidTextures.isEmpty()) {
throw new GradleException("Only Fun natural-distribution contract is incomplete: models=${missingModels}, textures=${invalidTextures}, hashes=${invalidTextureHashes}")
}
def fireworkFailures = []
if (!javaText.contains("class SkinFaceFireworkItem extends FireworkRocketItem")) fireworkFailures << "SkinFaceFireworkItem"
if (!javaText.contains("enum SkinFacePortrait")) fireworkFailures << "SkinFacePortrait"
if (!javaText.contains("class SkinFaceFireworkExplosions")) fireworkFailures << "SkinFaceFireworkExplosions"
if (!javaText.contains("CHRISM(")) fireworkFailures << "CHRISM"
if (!javaText.contains("DUNCAN(")) fireworkFailures << "DUNCAN"
if (!javaText.contains("0x4A9DFC")) fireworkFailures << "nourraEyes"
if (!javaText.contains("TRANSPARENT")) fireworkFailures << "TRANSPARENT"
if (!javaText.contains("class SkinFaceFireworkClient")) fireworkFailures << "client"
if (!javaText.contains("DustParticleOptions")) fireworkFailures << "dust"
if (!javaText.contains("PIXEL = 1.85D")) fireworkFailures << "pixel"
if (!javaText.contains("LARGE_PIXEL = 2.7D")) fireworkFailures << "largePixel"
if (!javaText.contains("LARGE_SPARK_SIZE = 5.15F")) fireworkFailures << "largeSpark"
if (!javaText.contains("SPARK_LIFETIME_TICKS = 38")) fireworkFailures << "lifetime"
if (!javaText.contains("new Fireworks(3, List.of())")) fireworkFailures << "fireworks"
if (!javaText.contains("LIFETIME_TRIM_TICKS = 5")) fireworkFailures << "trim"
if (!javaText.contains("onlyfun\$midFlightLifetime")) fireworkFailures << "midFlight"
if (!javaText.contains("onlyfun\$drawSkinFace")) fireworkFailures << "drawSkinFace"
if (!javaText.contains("OnlyFunRegistries.skinFireworks()")) fireworkFailures << "tab"
if (!file("src/main/resources/onlyfun.mixins.json").text.contains("FireworkRocketLifetimeMixin")) fireworkFailures << "commonMixin"
if (!file("src/main/resources/onlyfun.client.mixins.json").text.contains("FireworkRocketEntityMixin")) fireworkFailures << "clientMixin"
if (!file("src/main/resources/onlyfun.client.mixins.json").text.contains("ParticleLifetimeAccessor")) fireworkFailures << "particleAccessor"
if (!file("src/main/resources/fabric.mod.json").text.contains("onlyfun.mixins.json")) fireworkFailures << "fabricCommon"
if (!file("src/main/resources/fabric.mod.json").text.contains("onlyfun.client.mixins.json")) fireworkFailures << "fabricClient"
fireworkIds.each { fireworkId ->
if (!file("src/main/resources/data/onlyfun/recipe/${fireworkId}_firework.json").text.contains("onlyfun:${fireworkId}_firework")) {
fireworkFailures << "recipe:${fireworkId}"
}
}
["fr_fr", "en_us", "ru_ru"].each { locale ->
def translations = new JsonSlurper().parse(file(
"src/main/resources/assets/onlyfun/lang/${locale}.json"))
if (!translations.containsKey("tooltip.onlyfun.skin_face_firework")) fireworkFailures << "tooltip:${locale}"
fireworkIds.each { fireworkId ->
if (translations["item.onlyfun.${fireworkId}_firework"] == null) {
fireworkFailures << "lang:${locale}:${fireworkId}"
}
}
}
if (!fireworkFailures.isEmpty()) {
throw new GradleException("Only Fun firework contract is incomplete: ${fireworkFailures}")
}
}
}
+174
View File
@@ -0,0 +1,174 @@
from pathlib import Path
from PIL import Image
TRANSPARENT = -1
PEOPLE = [
("chrism", "ChrisM", "red_dye"),
("kaninscheun", "Kaninscheun", "yellow_dye"),
("poupoutain", "Poupoutain", "light_gray_dye"),
("lbeast", "lBeast", "brown_dye"),
("creveforest", "CreveForest", "green_dye"),
("sacdchips", "SacDChips", "orange_dye"),
("vaselline", "Vaselline", "white_dye"),
("duncan", "Duncan", "pink_dye"),
]
ROOT = Path(__file__).resolve().parents[2]
def rgb(pixel):
red, green, blue, _alpha = pixel
return (red << 16) | (green << 8) | blue
def extract(path):
image = Image.open(path).convert("RGBA")
face = []
hood = []
hood_top = []
inner_top = []
for y in range(8, 16):
for x in range(8, 16):
face.append(rgb(image.getpixel((x, y))))
for y in range(8, 16):
for x in range(40, 48):
red, green, blue, alpha = image.getpixel((x, y))
hood.append(TRANSPARENT if alpha < 128 else (red << 16) | (green << 8) | blue)
for y in range(6, 8):
for x in range(8, 16):
inner_top.append(rgb(image.getpixel((x, y))))
for y in range(6, 8):
for x in range(40, 48):
red, green, blue, alpha = image.getpixel((x, y))
if alpha < 128:
hood_top.append(inner_top[(y - 6) * 8 + (x - 40)])
else:
hood_top.append((red << 16) | (green << 8) | blue)
return face, hood, hood_top
def fmt(values):
lines = []
for index in range(0, len(values), 8):
chunk = values[index:index + 8]
parts = ["-1" if value == TRANSPARENT else f"0x{value:06X}" for value in chunk]
comma = "," if index + 8 < len(values) else ""
lines.append("\t\t" + ", ".join(parts) + comma)
return "\n".join(lines)
NOURRA_FACE = [
0x000000, 0x020202, 0x0A0A0A, 0x111111, 0x111111, 0x0A0A0A, 0x020202, 0x000000,
0x020202, 0x0A0A0A, 0x111111, 0x181818, 0x181818, 0x111111, 0x0A0A0A, 0x020202,
0x0A0A0A, 0x111111, 0x181818, 0x212121, 0x212121, 0x181818, 0x111111, 0x0A0A0A,
0x111111, 0x181818, 0x212121, 0x2B2B2B, 0x2B2B2B, 0x212121, 0x181818, 0x111111,
0x111111, 0x000000, 0x000000, 0xFFF0E1, 0xFFF0E1, 0x000000, 0x000000, 0x111111,
0x0A0A0A, 0xFFFFFF, 0x4A9DFC, 0xFDE8D7, 0xFFF0E1, 0x4A9DFC, 0xFFFFFF, 0x0A0A0A,
0x020202, 0xFFFFFF, 0x4A9DFC, 0xFDE8D7, 0xFDE8D7, 0x4A9DFC, 0xFFFFFF, 0x020202,
0x000000, 0xF0C6A5, 0xF7D5B9, 0xFCE1CA, 0xFCE1CA, 0xF7D5B9, 0xF0C6A5, 0x000000,
]
NOURRA_HOOD = [
0x000000, 0x0D0D0D, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0x0D0D0D, 0x000000,
0x0D0D0D, 0x707070, 0xD8D8D8, 0xE5E5E5, 0xE5E5E5, 0xD8D8D8, 0x707070, 0x0D0D0D,
0xCBCBCB, 0xD8D8D8, 0xFFFFFF, 0x212121, 0x212121, 0x181818, 0xD8D8D8, 0xCBCBCB,
0xD8D8D8, 0x181818, 0x212121, 0x2B2B2B, 0x2B2B2B, 0x212121, 0x181818, 0xD8D8D8,
0x111111, 0x181818, 0x212121, 0x2B2B2B, TRANSPARENT, TRANSPARENT, TRANSPARENT, 0x111111,
0x0A0A0A, 0x111111, 0x181818, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT,
0x020202, 0x0A0A0A, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT,
TRANSPARENT, 0x020202, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT, TRANSPARENT,
]
NOURRA_TOP = [
0xBEBEBE, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0xBEBEBE,
0xB8B8B8, 0xB8B8B8, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0xB8B8B8, 0xB8B8B8,
]
def main():
entries = [("nourra", NOURRA_FACE, NOURRA_HOOD, NOURRA_TOP)]
for ident, _display, _dye in PEOPLE:
face, hood, top = extract(ROOT / "art" / "skins" / f"{ident}.png")
entries.append((ident, face, hood, top))
print(ident, "hood opaque", sum(1 for value in hood if value != TRANSPARENT))
out = ROOT / "src" / "main" / "java" / "fr" / "koka99cab" / "sanctuary26" / "onlyfun" / "item" / "SkinFacePortrait.java"
chunks = [
"package fr.koka99cab.sanctuary26.onlyfun.item;\n\n",
"import net.minecraft.world.item.ItemStack;\n\n",
"/** Baked 8x8 inner face, hood overlay and hood-top strip for each skin firework. */\n",
"public enum SkinFacePortrait {\n",
]
for index, (ident, face, hood, top) in enumerate(entries):
comma = "," if index + 1 < len(entries) else ";"
chunks.append(
f"\t{ident.upper()}(\"{ident}\", new int[] {{\n{fmt(face)}\n\t}}, new int[] {{\n{fmt(hood)}\n\t}}, new int[] {{\n{fmt(top)}\n\t}}){comma}\n"
)
chunks.append("""
public static final int WIDTH = 8;
public static final int HEIGHT = 8;
public static final int TRANSPARENT = -1;
private final String id;
private final int[] face;
private final int[] hood;
private final int[] hoodTop;
SkinFacePortrait(String id, int[] face, int[] hood, int[] hoodTop) {
this.id = id;
this.face = face;
this.hood = hood;
this.hoodTop = hoodTop;
}
public String id() {
return id;
}
public String itemId() {
return id + \"_firework\";
}
public int[] face() {
return face;
}
public int[] hood() {
return hood;
}
public int[] hoodTop() {
return hoodTop;
}
public int opaqueHoodPixels() {
int count = 0;
for (int color : hood) {
if (color != TRANSPARENT) count++;
}
return count;
}
public int[] portrait() {
int[] pixels = new int[WIDTH * (HEIGHT + 2)];
System.arraycopy(hoodTop, 0, pixels, 0, hoodTop.length);
for (int index = 0; index < face.length; index++) {
pixels[hoodTop.length + index] = hood[index] == TRANSPARENT ? face[index] : hood[index];
}
return pixels;
}
public int portraitHeight() {
return HEIGHT + hoodTop.length / WIDTH;
}
public static SkinFacePortrait of(ItemStack stack) {
if (stack.isEmpty() || !(stack.getItem() instanceof SkinFaceFireworkItem item)) return null;
return item.portrait();
}
}
""")
out.write_text("".join(chunks), encoding="utf-8")
print("wrote", out)
if __name__ == "__main__":
main()
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -0,0 +1,47 @@
from pathlib import Path
IDS = [
("chrism", "red_dye"),
("kaninscheun", "yellow_dye"),
("poupoutain", "light_gray_dye"),
("lbeast", "brown_dye"),
("creveforest", "green_dye"),
("sacdchips", "orange_dye"),
("vaselline", "white_dye"),
("duncan", "pink_dye"),
]
ROOT = Path(__file__).resolve().parents[2] / "src" / "main" / "resources"
def main():
for ident, dye in IDS:
(ROOT / "assets" / "onlyfun" / "items" / f"{ident}_firework.json").write_text(
'{\n\t"model": {\n\t\t"type": "minecraft:model",\n\t\t"model": "onlyfun:item/%s_firework"\n\t}\n}\n' % ident,
encoding="utf-8",
)
(ROOT / "assets" / "onlyfun" / "models" / "item" / f"{ident}_firework.json").write_text(
'{\n\t"parent": "minecraft:item/generated",\n\t"textures": {\n\t\t"layer0": "onlyfun:item/%s_firework"\n\t}\n}\n' % ident,
encoding="utf-8",
)
(ROOT / "data" / "onlyfun" / "recipe" / f"{ident}_firework.json").write_text(
"""{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:%s",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:%s_firework"
}
}
""" % (dye, ident),
encoding="utf-8",
)
print("wrote", ident)
if __name__ == "__main__":
main()
@@ -1,6 +1,6 @@
package fr.koka99cab.sanctuary26.onlyfun.client;
import fr.koka99cab.sanctuary26.onlyfun.item.SkinFaceFireworkExplosions;
import fr.koka99cab.sanctuary26.onlyfun.item.SkinFacePortrait;
import fr.koka99cab.sanctuary26.onlyfun.mixin.client.ParticleLifetimeAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.Particle;
@@ -40,9 +40,11 @@ public final class SkinFaceFireworkClient {
if (right.lengthSqr() < 1.0E-6D) right = new Vec3(1.0D, 0.0D, 0.0D);
right = right.normalize();
Vec3 up = new Vec3(0.0D, 1.0D, 0.0D);
int[] pixels = SkinFaceFireworkExplosions.portrait();
int width = SkinFaceFireworkExplosions.WIDTH;
int height = SkinFaceFireworkExplosions.portraitHeight();
SkinFacePortrait portrait = SkinFacePortrait.of(rocket.getItem());
if (portrait == null) return;
int[] pixels = portrait.portrait();
int width = SkinFacePortrait.WIDTH;
int height = portrait.portraitHeight();
boolean large = largeBurst(rocket);
double pixel = burstPixel(large);
float sparkSize = burstSparkSize(large);
@@ -1,13 +1,12 @@
package fr.koka99cab.sanctuary26.onlyfun.item;
import fr.koka99cab.sanctuary26.onlyfun.registry.OnlyFunRegistries;
import java.util.List;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.Fireworks;
/**
* Baked Nourra head (NameMC 6166a439e9354904): inner face, hood overlay, hood top.
* The portrait is drawn client-side with firework sparks.
* Other skin fireworks reuse the same flight rules via {@link SkinFacePortrait}.
*/
public final class SkinFaceFireworkExplosions {
public static final int WIDTH = 8;
@@ -40,13 +39,12 @@ public final class SkinFaceFireworkExplosions {
0xBEBEBE, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0xBEBEBE,
0xB8B8B8, 0xB8B8B8, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0xB8B8B8, 0xB8B8B8
};
/** Vanilla flight 3 minus half a gunpowder step, so the burst sits between 2 and 3. */
public static final int LIFETIME_TRIM_TICKS = 5;
private SkinFaceFireworkExplosions() {
}
/** Vanilla flight 3 minus half a gunpowder step, so the burst sits between 2 and 3. */
public static final int LIFETIME_TRIM_TICKS = 5;
public static Fireworks defaultFireworks() {
return new Fireworks(3, List.of());
}
@@ -56,7 +54,7 @@ public final class SkinFaceFireworkExplosions {
}
public static boolean isSkinFaceRocket(ItemStack stack) {
return !stack.isEmpty() && stack.is(OnlyFunRegistries.NOURRA_FIREWORK);
return SkinFacePortrait.of(stack) != null;
}
public static int opaqueHoodPixels() {
@@ -69,15 +67,10 @@ public final class SkinFaceFireworkExplosions {
/** Hood top (2 rows) then the 8×8 face with the hood overlay composited. */
public static int[] portrait() {
int[] pixels = new int[WIDTH * (HEIGHT + 2)];
System.arraycopy(HOOD_TOP, 0, pixels, 0, HOOD_TOP.length);
for (int index = 0; index < FACE.length; index++) {
pixels[HOOD_TOP.length + index] = HOOD[index] == TRANSPARENT ? FACE[index] : HOOD[index];
}
return pixels;
return SkinFacePortrait.NOURRA.portrait();
}
public static int portraitHeight() {
return HEIGHT + HOOD_TOP.length / WIDTH;
return SkinFacePortrait.NOURRA.portraitHeight();
}
}
@@ -0,0 +1,30 @@
package fr.koka99cab.sanctuary26.onlyfun.item;
import java.util.function.Consumer;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.FireworkRocketItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.component.TooltipDisplay;
/** Firework rocket that bursts into a baked skin face. */
public final class SkinFaceFireworkItem extends FireworkRocketItem {
private final SkinFacePortrait portrait;
public SkinFaceFireworkItem(SkinFacePortrait portrait, Properties properties) {
super(properties);
this.portrait = portrait;
}
public SkinFacePortrait portrait() {
return portrait;
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, TooltipDisplay display,
Consumer<Component> tooltip, TooltipFlag flag) {
tooltip.accept(Component.translatable("tooltip.onlyfun.skin_face_firework").withStyle(ChatFormatting.AQUA));
super.appendHoverText(stack, context, display, tooltip, flag);
}
}
@@ -0,0 +1,269 @@
package fr.koka99cab.sanctuary26.onlyfun.item;
import net.minecraft.world.item.ItemStack;
/** Baked 8x8 inner face, hood overlay and hood-top strip for each skin firework. */
public enum SkinFacePortrait {
NOURRA("nourra", new int[] {
0x000000, 0x020202, 0x0A0A0A, 0x111111, 0x111111, 0x0A0A0A, 0x020202, 0x000000,
0x020202, 0x0A0A0A, 0x111111, 0x181818, 0x181818, 0x111111, 0x0A0A0A, 0x020202,
0x0A0A0A, 0x111111, 0x181818, 0x212121, 0x212121, 0x181818, 0x111111, 0x0A0A0A,
0x111111, 0x181818, 0x212121, 0x2B2B2B, 0x2B2B2B, 0x212121, 0x181818, 0x111111,
0x111111, 0x000000, 0x000000, 0xFFF0E1, 0xFFF0E1, 0x000000, 0x000000, 0x111111,
0x0A0A0A, 0xFFFFFF, 0x4A9DFC, 0xFDE8D7, 0xFFF0E1, 0x4A9DFC, 0xFFFFFF, 0x0A0A0A,
0x020202, 0xFFFFFF, 0x4A9DFC, 0xFDE8D7, 0xFDE8D7, 0x4A9DFC, 0xFFFFFF, 0x020202,
0x000000, 0xF0C6A5, 0xF7D5B9, 0xFCE1CA, 0xFCE1CA, 0xF7D5B9, 0xF0C6A5, 0x000000
}, new int[] {
0x000000, 0x0D0D0D, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0x0D0D0D, 0x000000,
0x0D0D0D, 0x707070, 0xD8D8D8, 0xE5E5E5, 0xE5E5E5, 0xD8D8D8, 0x707070, 0x0D0D0D,
0xCBCBCB, 0xD8D8D8, 0xFFFFFF, 0x212121, 0x212121, 0x181818, 0xD8D8D8, 0xCBCBCB,
0xD8D8D8, 0x181818, 0x212121, 0x2B2B2B, 0x2B2B2B, 0x212121, 0x181818, 0xD8D8D8,
0x111111, 0x181818, 0x212121, 0x2B2B2B, -1, -1, -1, 0x111111,
0x0A0A0A, 0x111111, 0x181818, -1, -1, -1, -1, -1,
0x020202, 0x0A0A0A, -1, -1, -1, -1, -1, -1,
-1, 0x020202, -1, -1, -1, -1, -1, -1
}, new int[] {
0xBEBEBE, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0xBEBEBE,
0xB8B8B8, 0xB8B8B8, 0xCBCBCB, 0xD8D8D8, 0xD8D8D8, 0xCBCBCB, 0xB8B8B8, 0xB8B8B8
}),
CHRISM("chrism", new int[] {
0xF59589, 0xF89C90, 0xFEA398, 0xFEA398, 0xFCA297, 0xF89B8F, 0xF2978B, 0xF49488,
0xF59589, 0xFB9D91, 0xFA9D92, 0xFCA095, 0xFCA095, 0xFCA095, 0xF89B8F, 0xF49488,
0xF59589, 0xFB9A8E, 0xFD9E93, 0xFDA196, 0xFDA196, 0xFD9E93, 0xFB9A8E, 0xFF988B,
0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E,
0xFE8B7E, 0x000000, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0x000000, 0xFD8B7D,
0xF67D70, 0xF68375, 0xFA897C, 0xFE8B7E, 0xFE8B7E, 0xFE8B7E, 0xF68375, 0xF67D70,
0x000000, 0xFFFFFF, 0x000000, 0x000000, 0x000000, 0x000000, 0xFFFFFF, 0x000000,
0xEE6858, 0x000000, 0x000000, 0xFF1408, 0xFC0C00, 0x000000, 0x000000, 0xEE6858
}, new int[] {
0xFF8071, 0xFF8274, 0xFF796A, 0xFA7B6C, 0xFE7E70, 0xF97769, 0xFB7F70, 0xFF7A6B,
0xF56E5E, 0xFF9185, 0xFF8375, 0xFF9084, 0xFB8A7E, 0xFE9286, 0xFF8B7E, 0xF68274,
0xFA7263, 0xFF9488, 0xFE9084, 0xFE8C80, 0xFF9286, 0xF77F72, 0xF89084, 0xF97465,
0xFF8273, 0xFF8E82, 0xFA8D81, 0xF68477, 0xF69186, 0xFF8F83, 0xFD9286, 0xFF7767,
0xFF8173, 0xFB887B, 0xFC9084, 0xFF9083, 0xFF978B, 0xFF8375, 0xF48A7E, 0xFF8173,
0xFD7D6E, -1, 0xF5897D, 0xFF8C7F, 0xF3877A, 0xFF897C, -1, 0xFF7060,
0xFC7667, 0xFF897B, 0xFF9488, -1, -1, 0xF37F72, 0xF89186, 0xFD7566,
0xFF8375, 0xFF7F70, 0xF88072, 0xF88173, 0xFC7869, 0xFF8173, 0xFF8678, 0xFF7C6D
}, new int[] {
0xF97566, 0xFF8C7F, 0xF4867A, 0xFF877A, 0xF4786A, 0xFF8678, 0xF97E70, 0xFF7F71,
0xFF897B, 0xFB7566, 0xFF8C7F, 0xF77F72, 0xF77769, 0xFF7C6E, 0xF88578, 0xF87B6D
}),
KANINSCHEUN("kaninscheun", new int[] {
0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D,
0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xFFCC66, 0xEAD900, 0xEDDF2D,
0xEAD900, 0xEDDF2D, 0xEAD900, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0xEDDF2D,
0xEAD900, 0x000000, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0x000000, 0xEDDF2D,
0xEAD900, 0x000000, 0x000000, 0xFFCC66, 0xFFCC66, 0x000000, 0x000000, 0xEDDF2D,
0xEAD900, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0xFFCC66, 0xEDDF2D,
0xEAD900, 0xFFCC66, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xFFCC66, 0xEDDF2D,
0xEAD900, 0xEAD900, 0xEDDF2D, 0xFFCC66, 0xFFCC66, 0xEAD900, 0xEAD900, 0xEDDF2D
}, new int[] {
-1, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, -1,
0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900,
0xEDDF2D, 0xEAD900, 0xEDDF2D, -1, -1, -1, 0xEDDF2D, 0xEAD900,
0xEDDF2D, 0xEAD900, -1, -1, -1, -1, -1, 0xEAD900,
0xEDDF2D, -1, -1, -1, -1, -1, -1, 0xEAD900,
0xEDDF2D, -1, -1, -1, -1, -1, -1, 0xEAD900,
0xEDDF2D, -1, -1, -1, -1, -1, -1, 0xEAD900,
-1, 0xEAD900, -1, -1, -1, -1, 0xEDDF2D, -1
}, new int[] {
0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900,
0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900, 0xEDDF2D, 0xEAD900
}),
POUPOUTAIN("poupoutain", new int[] {
0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456,
0x4B5456, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0x4B5456,
0x4B5456, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0x342404, 0xE7E6E4, 0x4B5456,
0x4B5456, 0xE7E6E4, 0x342404, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0x4B5456,
0x4B5456, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0x4B5456,
0x4B5456, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0x342404, 0xE0DFDE, 0xE7E6E4, 0x4B5456,
0x4B5456, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0xE7E6E4, 0x4B5456,
0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456
}, new int[] {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1
}, new int[] {
0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456, 0x4B5456,
0x414B4C, 0x414B4C, 0x414B4C, 0x414B4C, 0x414B4C, 0x414B4C, 0x414B4C, 0x414B4C
}),
LBEAST("lbeast", new int[] {
0x8A6C30, 0x8A6B31, 0x644B1A, 0x5D4B1E, 0x896F37, 0x80672A, 0x614B1A, 0x4C3910,
0x957538, 0x816C34, 0x6D5521, 0x715B20, 0xA88C44, 0x9C7E3B, 0x7F6625, 0x7D6325,
0xB59F6D, 0xC1AC74, 0xC8B378, 0xD0BB7C, 0xD9C382, 0xE7CF8A, 0xD2BC7E, 0xC6A574,
0xB39C6C, 0x2B2324, 0x2B2324, 0xD5BA80, 0xD7BE80, 0x2B2324, 0x2B2324, 0xCBA977,
0xDCC285, 0xBAA0A6, 0x42597E, 0xF1D491, 0xD7BD7F, 0x42597E, 0xBAA0A6, 0xECC48B,
0xEACC8C, 0xFAF3F5, 0x87A6D2, 0xFDDB98, 0xDCBE81, 0x87A6D2, 0xFAF3F5, 0xF1C88E,
0xE4C082, 0xF6D695, 0xFBDD96, 0xFBE197, 0xFBE197, 0xFDDC95, 0xF6D695, 0xEBC288,
0xE9C183, 0xEFC68A, 0xF6D695, 0xFDDC94, 0xFBE197, 0xF6D695, 0xF4C98C, 0xDFB67D
}, new int[] {
0x7E652E, 0xC5A253, 0xC5A253, 0xBB984A, 0xD0A64E, 0xBB984A, 0xC5A253, 0x715B29,
0x947438, 0xEAC269, 0x96772C, 0xB69045, 0xD0A64E, 0xBB984A, 0xC5A253, 0x7E652E,
0xB49043, 0xD0A64E, -1, 0xD0A64E, 0xE4C368, 0xBB984A, 0xD0A64E, 0x8A6E32,
0x96772C, -1, -1, -1, -1, 0xBB9853, 0xD1AD5C, 0xB18D46,
0xD0A64E, -1, -1, -1, -1, -1, -1, 0x9C7D39,
-1, -1, -1, -1, -1, -1, -1, 0x9C7D39,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1
}, new int[] {
0x846932, 0x907336, 0xA18340, 0xAE8E45, 0xAE8E45, 0x886F36, 0x7B6431, 0x6E5A2C,
0x7A6029, 0x886F36, 0x95793B, 0xA18340, 0xA18340, 0x95793B, 0x886F36, 0x7B6431
}),
CREVEFOREST("creveforest", new int[] {
0x2D4C54, 0x2D4C54, 0x2D4C54, 0x2D4C54, 0x355C5E, 0x2D4C54, 0x2D4C54, 0x2D4C54,
0x2D4C54, 0x2D4C54, 0x355C5E, 0x355C5E, 0x355C5E, 0x355C5E, 0x2D4C54, 0x2D4C54,
0x2D4C54, 0x355C5E, 0x79A88F, 0x8FC49B, 0x79A88F, 0x79A88F, 0x355C5E, 0x2D4C54,
0x355C5E, 0x79A88F, 0x8FC49B, 0x9ED69C, 0x8FC49B, 0x8FC49B, 0x79A88F, 0x355C5E,
0x355C5E, 0x1E2E33, 0x1E2E33, 0xB7E8A9, 0x9ED69C, 0x1E2E33, 0x1E2E33, 0x355C5E,
0x1E2E33, 0x9BB0AC, 0x344C46, 0xD3F5BA, 0xB7E8A9, 0x344C46, 0x9BB0AC, 0x1E2E33,
0x2D4C54, 0xEBEBEB, 0x79B8AB, 0xD3F5BA, 0xB7E8A9, 0x79B8AB, 0xEBEBEB, 0x355C5E,
0x2D4C54, 0x8FC49B, 0xB7E8A9, 0x9ED69C, 0xB7E8A9, 0xB7E8A9, 0x8FC49B, 0x355C5E
}, new int[] {
-1, 0x549C62, 0x4D8C64, 0x4D8C64, 0x549C62, 0x3D785D, 0x4D8C64, -1,
0x549C62, 0x549C62, 0x4D8C64, 0x4D8C64, 0x4D8C64, 0x3D785D, 0x4D8C64, 0x549C62,
0x4D8C64, 0x4D8C64, 0x3D785D, 0x3D785D, 0x3D785D, 0x355C5E, 0x3D785D, 0x4D8C64,
0x3D785D, 0x3D785D, 0x355C5E, -1, 0x355C5E, 0x2D4C54, 0x355C5E, 0x3D785D,
0x3D785D, -1, 0x2D4C54, -1, -1, -1, 0x355C5E, 0x3D785D,
0x355C5E, -1, -1, -1, -1, -1, -1, 0x355C5E,
0x2D4C54, -1, -1, -1, -1, -1, -1, 0x2D4C54,
-1, -1, -1, -1, -1, -1, -1, -1
}, new int[] {
0x355C5E, 0x355C5E, 0x355C5E, 0x355C5E, 0x3D785D, 0x355C5E, 0x2D4C54, 0x355C5E,
0x2D4C54, 0x549C62, 0x4D8C64, 0x4D8C64, 0x549C62, 0x3D785D, 0x4D8C64, 0x355C5E
}),
SACDCHIPS("sacdchips", new int[] {
0x3E1A05, 0x421D05, 0x391904, 0x421C06, 0x391904, 0x632C08, 0x3D1B05, 0x552607,
0x421D05, 0x421D05, 0x391904, 0xF1DACD, 0xF2DDD1, 0xEFD7C9, 0xEED4C5, 0x632C08,
0xEBCCBA, 0xECCFBE, 0xEDD1C1, 0xE7C3AE, 0xEDD1C1, 0xEED4C5, 0xF2DDD1, 0xECCFBE,
0xECCFBE, 0x341704, 0x341704, 0xE7C3AE, 0xEBCCBA, 0x341704, 0x341704, 0xF1DACD,
0xEBCCBA, 0xEEEEEE, 0x602F10, 0xEDD1C1, 0xF2DDD1, 0x602F10, 0xEEEEEE, 0xEDD1C1,
0xE7C3AE, 0xEDD1C1, 0xE7C3AE, 0xF2DDD1, 0xF1DACD, 0xEDD1C1, 0xE7C3AE, 0xEDD1C1,
0xE6C0AA, 0xECCFBE, 0xEBCCBA, 0x000000, 0x000000, 0xEDD1C1, 0xEAC9B6, 0xEBCCBA,
0xEAC9B6, 0xECCFBE, 0xF2DDD1, 0xECCFBE, 0xEAC9B6, 0xF1DACD, 0xECCFBE, 0xF1DACD
}, new int[] {
-1, 0x180A02, 0x261003, 0x2B1204, 0x341604, 0x210E03, 0x2F1404, -1,
-1, -1, -1, 0x2B1204, 0x210E03, 0x471E06, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 0x261003, 0x180A02, 0x210E03, 0x1D0C02, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1
}, new int[] {
0x3E1A05, 0x3E1A05, 0x210E03, 0x1D0C02, 0x341604, 0x180A02, 0x2F1404, 0x1D0C02,
0x391805, 0x421C06, 0x421C06, 0x3E1A05, 0x471E06, 0x1D0C02, 0x341604, 0x341604
}),
VASELLINE("vaselline", new int[] {
0xEBE176, 0xEBE176, 0xEBE176, 0xE8DC5F, 0xE8DC5F, 0xE8DC5F, 0xEBE176, 0xEBE176,
0xEBE176, 0xE8DC5F, 0xE8D7B1, 0xE8D7B1, 0xE8D7B1, 0xE8D7B1, 0xE8DC5F, 0xEBE176,
0xE8DC5F, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xE8DC5F,
0xE8DC5F, 0xFFFFFF, 0x6F9EE8, 0xE8D7B1, 0xE8D7B1, 0x6F9EE8, 0xFFFFFF, 0xE8DC5F,
0xE8DC5F, 0xE8D7B1, 0xE8D7B1, 0xEEE1C5, 0xEEE1C5, 0xE8D7B1, 0xE8D7B1, 0xE8DC5F,
0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5,
0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xE2CD9D, 0xE2CD9D, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5,
0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5, 0xEEE1C5
}, new int[] {
0xEBE176, 0xEBE176, 0xE8DC5F, 0xE8DC5F, 0xE8DC5F, 0xE8DC5F, 0xEBE176, 0xEBE176,
0xEBE176, 0xE8DC5F, -1, -1, -1, -1, 0xE8DC5F, 0xEBE176,
0xEBE176, -1, -1, -1, -1, -1, -1, 0xE8DC5F,
0xE8DC5F, -1, -1, -1, -1, -1, -1, 0xE8DC5F,
0xE8DC5F, -1, -1, -1, -1, -1, -1, 0xE8DC5F,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1
}, new int[] {
0xEBE176, 0xE8DC5F, 0xE8DC5F, 0xEBE176, 0xEBE176, 0xE8DC5F, 0xE8DC5F, 0xE8DC5F,
0xEBE176, 0xEBE176, 0xEBE176, 0xEBE176, 0xEBE176, 0xEBE176, 0xEBE176, 0xEBE176
}),
DUNCAN("duncan", new int[] {
0x9D5330, 0x9D5330, 0x9D5330, 0x9D5330, 0x9D5330, 0x9D5330, 0x9D5330, 0x9D5330,
0xFFD6AE, 0xFFD7AE, 0xFFD7AE, 0xFFD6AE, 0xFFD6AE, 0xFED7AE, 0xFFD7AF, 0xFFD7AE,
0xFFD7AE, 0xAD3B11, 0xAC3A10, 0xFFD7AE, 0xFFD7AE, 0xAD3B10, 0xAC3B11, 0xFFD6AF,
0xFED6AF, 0xFEFFFF, 0x783018, 0xFFD7AE, 0xFFD7AE, 0xFEFFFE, 0x793019, 0xFFD6AF,
0xFFD6AE, 0x783018, 0x010000, 0xFFD7AF, 0xFED7AE, 0x010100, 0x783018, 0xFFD7AF,
0xFED7AF, 0xFFD7AE, 0xFFD7AF, 0xFED6AF, 0xFED7AE, 0xFED7AE, 0xFED7AF, 0xFFD6AE,
0xFED7AE, 0xFED7AF, 0xFED7AE, 0xCB97A0, 0xCB96A0, 0xFED7AE, 0xFFD7AE, 0xFFD6AE,
0xFFD7AE, 0xFED7AE, 0xFFD7AE, 0xFFD7AF, 0xFFD7AE, 0xFFD7AE, 0xFFD7AE, 0xFED7AE
}, new int[] {
0x9D5330, 0xBC5D30, 0x9D5330, 0x88492A, 0x9D5330, 0x9D5330, 0x88492A, 0x9D5330,
0x9D5330, -1, 0x88492A, -1, -1, 0xBC5D30, -1, 0x9D5330,
-1, 0xE6AB35, 0xE7AA34, -1, -1, 0xE6AA34, 0xE7AA34, -1,
0xE6AB34, -1, -1, 0xE7AB35, 0xE7AB35, -1, -1, 0xE6AB35,
0xE7AB35, -1, -1, 0xE6AB35, 0xE6AA34, -1, -1, 0xE6AB35,
-1, 0xE6AB34, 0xE6AB35, -1, -1, 0xE6AB35, 0xE6AB34, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1
}, new int[] {
0x9D5330, 0x9D5330, 0x9D5330, 0x9D5330, 0x88492A, 0x9D5330, 0x9D5330, 0x88492A,
0x9D5330, 0x9D5330, 0x9D5330, 0xBC5D30, 0x9D5330, 0x9D5330, 0x9D5330, 0x9D5330
});
public static final int WIDTH = 8;
public static final int HEIGHT = 8;
public static final int TRANSPARENT = -1;
private final String id;
private final int[] face;
private final int[] hood;
private final int[] hoodTop;
SkinFacePortrait(String id, int[] face, int[] hood, int[] hoodTop) {
this.id = id;
this.face = face;
this.hood = hood;
this.hoodTop = hoodTop;
}
public String id() {
return id;
}
public String itemId() {
return id + "_firework";
}
public int[] face() {
return face;
}
public int[] hood() {
return hood;
}
public int[] hoodTop() {
return hoodTop;
}
public int opaqueHoodPixels() {
int count = 0;
for (int color : hood) {
if (color != TRANSPARENT) count++;
}
return count;
}
public int[] portrait() {
int[] pixels = new int[WIDTH * (HEIGHT + 2)];
System.arraycopy(hoodTop, 0, pixels, 0, hoodTop.length);
for (int index = 0; index < face.length; index++) {
pixels[hoodTop.length + index] = hood[index] == TRANSPARENT ? face[index] : hood[index];
}
return pixels;
}
public int portraitHeight() {
return HEIGHT + hoodTop.length / WIDTH;
}
public static SkinFacePortrait of(ItemStack stack) {
if (stack.isEmpty()) return null;
if (stack.getItem() instanceof SkinFaceFireworkItem item) return item.portrait();
if (stack.getItem() instanceof NourraFireworkItem) return NOURRA;
return null;
}
}
@@ -8,6 +8,7 @@ import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
public final class OnlyFunCreativeTab {
@@ -29,6 +30,9 @@ public final class OnlyFunCreativeTab {
output.accept(OnlyFunRegistries.SPAWN_EGG_LOOTBOX);
output.accept(OnlyFunRegistries.ANOMALY_LOOTBOX);
output.accept(OnlyFunRegistries.NOURRA_FIREWORK);
for (Item firework : OnlyFunRegistries.skinFireworks()) {
if (firework != OnlyFunRegistries.NOURRA_FIREWORK) output.accept(firework);
}
output.accept(AbjectionRegistries.SHIT_BALL);
output.accept(AbjectionRegistries.SHIT_CUBE_ITEM);
})
@@ -3,8 +3,10 @@ package fr.koka99cab.sanctuary26.onlyfun.registry;
import fr.koka99cab.sanctuary26.onlyfun.OnlyFunMod;
import fr.koka99cab.sanctuary26.onlyfun.block.LuckyBlockBlock;
import fr.koka99cab.sanctuary26.onlyfun.item.LootboxItem;
import fr.koka99cab.sanctuary26.onlyfun.item.SkinFaceFireworkExplosions;
import fr.koka99cab.sanctuary26.onlyfun.item.NourraFireworkItem;
import fr.koka99cab.sanctuary26.onlyfun.item.SkinFaceFireworkExplosions;
import fr.koka99cab.sanctuary26.onlyfun.item.SkinFaceFireworkItem;
import fr.koka99cab.sanctuary26.onlyfun.item.SkinFacePortrait;
import fr.koka99cab.sanctuary26.onlyfun.loot.OnlyFunGenerator;
import fr.koka99cab.sanctuary26.onlyfun.loot.OnlyFunSource;
import java.util.function.Function;
@@ -37,6 +39,14 @@ public final class OnlyFunRegistries {
public static final Item NOURRA_FIREWORK = registerItem("nourra_firework",
properties -> new NourraFireworkItem(properties.stacksTo(64)
.component(DataComponents.FIREWORKS, SkinFaceFireworkExplosions.defaultFireworks())));
public static final Item CHRISM_FIREWORK = registerSkinFirework(SkinFacePortrait.CHRISM);
public static final Item KANINSCHEUN_FIREWORK = registerSkinFirework(SkinFacePortrait.KANINSCHEUN);
public static final Item POUPOUTAIN_FIREWORK = registerSkinFirework(SkinFacePortrait.POUPOUTAIN);
public static final Item LBEAST_FIREWORK = registerSkinFirework(SkinFacePortrait.LBEAST);
public static final Item CREVEFOREST_FIREWORK = registerSkinFirework(SkinFacePortrait.CREVEFOREST);
public static final Item SACDCHIPS_FIREWORK = registerSkinFirework(SkinFacePortrait.SACDCHIPS);
public static final Item VASELLINE_FIREWORK = registerSkinFirework(SkinFacePortrait.VASELLINE);
public static final Item DUNCAN_FIREWORK = registerSkinFirework(SkinFacePortrait.DUNCAN);
private static boolean initialized;
private OnlyFunRegistries() {
@@ -52,6 +62,13 @@ public final class OnlyFunRegistries {
};
}
public static Item[] skinFireworks() {
return new Item[] {
NOURRA_FIREWORK, CHRISM_FIREWORK, KANINSCHEUN_FIREWORK, POUPOUTAIN_FIREWORK,
LBEAST_FIREWORK, CREVEFOREST_FIREWORK, SACDCHIPS_FIREWORK, VASELLINE_FIREWORK, DUNCAN_FIREWORK
};
}
public static void initialize() {
if (initialized) {
return;
@@ -66,6 +83,11 @@ public final class OnlyFunRegistries {
OnlyFunMod.LOGGER.debug("[{}] Item and block registries initialized.", OnlyFunMod.DISPLAY_NAME);
}
private static Item registerSkinFirework(SkinFacePortrait portrait) {
return registerItem(portrait.itemId(), properties -> new SkinFaceFireworkItem(portrait,
properties.stacksTo(64).component(DataComponents.FIREWORKS, SkinFaceFireworkExplosions.defaultFireworks())));
}
private static Item registerItem(String path, Function<Item.Properties, Item> factory) {
ResourceKey<Item> key = ResourceKey.create(Registries.ITEM, OnlyFunMod.id(path));
return Registry.register(BuiltInRegistries.ITEM, key, factory.apply(new Item.Properties().setId(key)));
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/chrism_firework"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/creveforest_firework"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/duncan_firework"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/kaninscheun_firework"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/lbeast_firework"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/poupoutain_firework"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/sacdchips_firework"
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "onlyfun:item/vaselline_firework"
}
}
@@ -7,7 +7,16 @@
"item.onlyfun.spawn_egg_lootbox": "Spawn Egg Lootbox",
"item.onlyfun.anomaly_lootbox": "Anomaly Lootbox",
"item.onlyfun.nourra_firework": "Nourra Firework",
"item.onlyfun.chrism_firework": "ChrisM Firework",
"item.onlyfun.kaninscheun_firework": "Kaninscheun Firework",
"item.onlyfun.poupoutain_firework": "Poupoutain Firework",
"item.onlyfun.lbeast_firework": "lBeast Firework",
"item.onlyfun.creveforest_firework": "CreveForest Firework",
"item.onlyfun.sacdchips_firework": "SacDChips Firework",
"item.onlyfun.vaselline_firework": "Vaselline Firework",
"item.onlyfun.duncan_firework": "Duncan Firework",
"tooltip.onlyfun.nourra_firework": "The burst paints the skin face, at normal or larger size.",
"tooltip.onlyfun.skin_face_firework": "The burst paints the skin face, at normal or larger size.",
"item.onlyfun.quality_gear": "Quality Gear",
"item.onlyfun.impossible_tool": "Impossible Tool",
"item.onlyfun.impossible_book": "Impossible Book",
@@ -7,7 +7,16 @@
"item.onlyfun.spawn_egg_lootbox": "Lootbox d'œufs",
"item.onlyfun.anomaly_lootbox": "Lootbox anomalie",
"item.onlyfun.nourra_firework": "Feu d'artifice Nourra",
"item.onlyfun.chrism_firework": "Feu d'artifice ChrisM",
"item.onlyfun.kaninscheun_firework": "Feu d'artifice Kaninscheun",
"item.onlyfun.poupoutain_firework": "Feu d'artifice Poupoutain",
"item.onlyfun.lbeast_firework": "Feu d'artifice lBeast",
"item.onlyfun.creveforest_firework": "Feu d'artifice CreveForest",
"item.onlyfun.sacdchips_firework": "Feu d'artifice SacDChips",
"item.onlyfun.vaselline_firework": "Feu d'artifice Vaselline",
"item.onlyfun.duncan_firework": "Feu d'artifice Duncan",
"tooltip.onlyfun.nourra_firework": "L'explosion dessine le visage, en taille normale ou plus grande.",
"tooltip.onlyfun.skin_face_firework": "L'explosion dessine le visage, en taille normale ou plus grande.",
"item.onlyfun.quality_gear": "Équipement de qualité",
"item.onlyfun.impossible_tool": "Outil impossible",
"item.onlyfun.impossible_book": "Livre impossible",
@@ -7,7 +7,16 @@
"item.onlyfun.spawn_egg_lootbox": "Лутбокс яиц призыва",
"item.onlyfun.anomaly_lootbox": "Лутбокс-аномалия",
"item.onlyfun.nourra_firework": "Фейерверк Нурры",
"item.onlyfun.chrism_firework": "Фейерверк ChrisM",
"item.onlyfun.kaninscheun_firework": "Фейерверк Kaninscheun",
"item.onlyfun.poupoutain_firework": "Фейерверк Poupoutain",
"item.onlyfun.lbeast_firework": "Фейерверк lBeast",
"item.onlyfun.creveforest_firework": "Фейерверк CreveForest",
"item.onlyfun.sacdchips_firework": "Фейерверк SacDChips",
"item.onlyfun.vaselline_firework": "Фейерверк Vaselline",
"item.onlyfun.duncan_firework": "Фейерверк Duncan",
"tooltip.onlyfun.nourra_firework": "Взрыв рисует лицо скина обычного или увеличенного размера.",
"tooltip.onlyfun.skin_face_firework": "Взрыв рисует лицо скина обычного или увеличенного размера.",
"item.onlyfun.quality_gear": "Качественное снаряжение",
"item.onlyfun.impossible_tool": "Невозможный инструмент",
"item.onlyfun.impossible_book": "Невозможная книга",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/chrism_firework"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/creveforest_firework"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/duncan_firework"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/kaninscheun_firework"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/lbeast_firework"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/poupoutain_firework"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/sacdchips_firework"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "onlyfun:item/vaselline_firework"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:red_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:chrism_firework"
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:green_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:creveforest_firework"
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:pink_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:duncan_firework"
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:yellow_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:kaninscheun_firework"
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:brown_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:lbeast_firework"
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:light_gray_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:poupoutain_firework"
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:orange_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:sacdchips_firework"
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
"minecraft:firework_rocket",
"minecraft:white_dye",
"minecraft:paper"
],
"result": {
"count": 1,
"id": "onlyfun:vaselline_firework"
}
}
@@ -5,7 +5,7 @@ import net.minecraft.SharedConstants;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.item.component.Fireworks;
/** Executable check for the baked Nourra face and hood firework contract. */
/** Executable check for baked skin-face firework portraits. */
public final class SkinFaceFireworkSmoke {
private SkinFaceFireworkSmoke() {
}
@@ -17,37 +17,47 @@ public final class SkinFaceFireworkSmoke {
}
public static void verify() {
require(SkinFaceFireworkExplosions.WIDTH == 8 && SkinFaceFireworkExplosions.HEIGHT == 8,
require(SkinFacePortrait.values().length == 9, "Skin firework roster drifted");
require(SkinFacePortrait.WIDTH == 8 && SkinFacePortrait.HEIGHT == 8,
"Face grid is no longer 8×8");
require(SkinFaceFireworkExplosions.FACE.length == 64, "Face palette length drifted");
require(SkinFaceFireworkExplosions.HOOD.length == 64, "Hood overlay length drifted");
require(SkinFaceFireworkExplosions.HOOD_TOP.length == 16, "Hood top strip length drifted");
require(SkinFaceFireworkExplosions.FACE[5 * 8 + 2] == 0x4A9DFC
&& SkinFaceFireworkExplosions.FACE[5 * 8 + 5] == 0x4A9DFC,
"Blue eyes are missing from the inner face");
require(SkinFaceFireworkExplosions.FACE[4 * 8 + 3] == 0xFFF0E1,
"Skin tone is missing from the baked face");
require(SkinFaceFireworkExplosions.HOOD[2] == 0xCBCBCB,
"Hood overlay is missing from the top of the face");
require(SkinFaceFireworkExplosions.HOOD[5 * 8 + 2] == 0x181818,
"Hood no longer covers the left eye");
require(SkinFaceFireworkExplosions.HOOD[5 * 8 + 5] == SkinFaceFireworkExplosions.TRANSPARENT,
"Hood opening no longer leaves the right eye visible");
require(SkinFaceFireworkExplosions.opaqueHoodPixels() == 43,
"Opaque hood pixel count drifted");
for (SkinFacePortrait portrait : SkinFacePortrait.values()) {
require(portrait.face().length == 64, portrait.id() + " face palette length drifted");
require(portrait.hood().length == 64, portrait.id() + " hood overlay length drifted");
require(portrait.hoodTop().length == 16, portrait.id() + " hood top strip length drifted");
int[] pixels = portrait.portrait();
require(pixels.length == 80 && portrait.portraitHeight() == 10,
portrait.id() + " portrait grid drifted");
require(portrait.itemId().equals(portrait.id() + "_firework"),
portrait.id() + " item id drifted");
}
require(SkinFacePortrait.NOURRA.face()[5 * 8 + 2] == 0x4A9DFC
&& SkinFacePortrait.NOURRA.face()[5 * 8 + 5] == 0x4A9DFC,
"Blue eyes are missing from the Nourra face");
require(SkinFacePortrait.NOURRA.face()[4 * 8 + 3] == 0xFFF0E1,
"Skin tone is missing from the baked Nourra face");
require(SkinFacePortrait.NOURRA.hood()[2] == 0xCBCBCB,
"Hood overlay is missing from the top of the Nourra face");
require(SkinFacePortrait.NOURRA.hood()[5 * 8 + 2] == 0x181818,
"Nourra hood no longer covers the left eye");
require(SkinFacePortrait.NOURRA.hood()[5 * 8 + 5] == SkinFacePortrait.TRANSPARENT,
"Nourra hood opening no longer leaves the right eye visible");
require(SkinFacePortrait.NOURRA.opaqueHoodPixels() == 43,
"Opaque Nourra hood pixel count drifted");
int[] nourra = SkinFacePortrait.NOURRA.portrait();
require(nourra[16 + 5 * 8 + 5] == 0x4A9DFC,
"Right eye is missing from the composited Nourra portrait");
require(nourra[2] == 0xD8D8D8,
"Hood top is missing from the Nourra portrait");
require(SkinFacePortrait.CHRISM.face()[6 * 8 + 1] == 0xFFFFFF,
"ChrisM eyes are missing from the baked face");
require(SkinFacePortrait.DUNCAN.face().length == 64,
"Duncan face is missing");
Fireworks fireworks = SkinFaceFireworkExplosions.defaultFireworks();
require(fireworks.flightDuration() == 3 && fireworks.explosions().isEmpty(),
"Default firework burst contract changed");
require(SkinFaceFireworkExplosions.LIFETIME_TRIM_TICKS == 5
&& SkinFaceFireworkExplosions.midFlightLifetime(45) == 40,
"Mid-flight lifetime trim drifted");
int[] portrait = SkinFaceFireworkExplosions.portrait();
require(portrait.length == 80 && SkinFaceFireworkExplosions.portraitHeight() == 10,
"Portrait grid drifted");
require(portrait[16 + 5 * 8 + 5] == 0x4A9DFC,
"Right eye is missing from the composited portrait");
require(portrait[2] == 0xD8D8D8,
"Hood top is missing from the portrait");
require(SkinFaceFireworkClient.PIXEL == 1.85D, "Portrait scale drifted");
require(SkinFaceFireworkClient.LARGE_PIXEL == 2.7D, "Large portrait scale drifted");
require(SkinFaceFireworkClient.burstPixel(false) == SkinFaceFireworkClient.PIXEL
@@ -57,7 +67,7 @@ public final class SkinFaceFireworkSmoke {
&& SkinFaceFireworkClient.burstSparkSize(true) == SkinFaceFireworkClient.LARGE_SPARK_SIZE,
"Large burst scale drifted");
require(SkinFaceFireworkClient.SPARK_LIFETIME_TICKS == 38, "Spark lifetime drifted");
System.out.println("Only Fun Nourra firework: 8×8 face with hood overlay ready.");
System.out.println("Only Fun skin fireworks: 9 baked faces with hood overlay ready.");
}
private static void require(boolean condition, String message) {