9
0
mirror of https://github.com/Kas-tle/java2bedrock.sh.git synced 2025-12-19 14:59:13 +00:00

Use Geyser mappings; smart texture atlasing

This commit is contained in:
Kas-tle
2022-07-30 11:46:03 +00:00
committed by GitHub
parent aa2781c660
commit 290fe51147
2 changed files with 82 additions and 109 deletions

3
.gitignore vendored
View File

@@ -9,3 +9,6 @@ parents.json
*.csv
*.temp
spritesheet.json
item_mappings.json
item_texture.json
spritesheet/

View File

@@ -130,79 +130,28 @@ status_message process "Iterating through all vanilla associated model JSONs to
if test -d "./assets/minecraft/models/item"; then confarg1="./assets/minecraft/models/item/*.json"; fi
if test -d "./assets/minecraft/models/block"; then confarg2="./assets/minecraft/models/block/*.json"; fi
# Download geyser mappings
status_message process "Downloading the latest geyser item mappings"
printf "\e[3m\e[37m"
echo
wget -nv --show-progress -O item_mappings.json https://raw.githubusercontent.com/GeyserMC/mappings/master/items.json
echo
wget -nv --show-progress -O item_texture.json https://raw.githubusercontent.com/Kas-tle/java2bedrockMappings/main/item_texture.json
echo
printf "${C_CLOSE}"
jq -n '[inputs | {(input_filename | sub("(.+)/(?<itemname>.*?).json"; .itemname)): .overrides?[]?}] |
jq --slurpfile item_texture item_texture.json --slurpfile item_mappings item_mappings.json -n '[inputs | {(input_filename | sub("(.+)/(?<itemname>.*?).json"; .itemname)): .overrides?[]?}] |
def maxdur($input):
({
"carrot_on_a_stick": 25,
"golden_axe": 32,
"golden_hoe": 32,
"golden_pickaxe": 32,
"golden_shovel": 32,
"golden_sword": 32,
"wooden_axe": 59,
"wooden_hoe": 59,
"wooden_pickaxe":59,
"wooden_shovel":59,
"wooden_sword": 59,
"fishing_rod": 64,
"flint_and_steel": 64,
"warped_fungus_on_a_stick": 100,
"sparkler": 100,
"glow_stick": 100,
"stone_axe": 131,
"stone_hoe": 131,
"stone_pickaxe":131,
"stone_shovel":131,
"stone_sword": 131,
"shears": 238,
"iron_axe": 250,
"iron_hoe": 250,
"iron_pickaxe": 250,
"iron_shovel": 250,
"iron_sword": 250,
"trident": 250,
"crossbow": 326,
"shield": 336,
"bow": 384,
"elytra": 432,
"diamond_axe": 1561,
"diamond_hoe": 1561,
"diamond_pickaxe": 1561,
"diamond_shovel": 1561,
"diamond_sword": 1561,
"netherite_axe": 2031,
"netherite_hoe": 2031,
"netherite_pickaxe": 2031,
"netherite_shovel": 2031,
"netherite_sword": 2031,
"leather_helmet": 55,
"leather_chestplate": 80,
"leather_leggings": 75,
"leather_boots": 65,
"gold_helmet": 77,
"gold_chestplate": 112,
"gold_leggings": 105,
"gold_boots": 91,
"chainmail_helmet": 165,
"chainmail_chestplate": 240,
"chainmail_leggings": 225,
"chainmail_boots": 195,
"iron_helmet": 165,
"iron_chestplate": 240,
"iron_leggings": 225,
"iron_boots": 195,
"diamond_helmet": 363,
"diamond_chestplate": 528,
"diamond_leggings": 495,
"diamond_boots": 429,
"netherite_helmet": 407,
"netherite_chestplate": 592,
"netherite_leggings": 555,
"netherite_boots": 481,
"turtle_helmet": 275
} | .[$input] // 1)
($item_mappings[] |
[to_entries | map(.key as $key | .value | .java_identifer = $key) | .[] | select(.max_damage)]
| map({(.java_identifer | split(":") | .[1]): (.max_damage)})
| add
| .[$input] // 1)
;
def bedrocktexture($input):
($item_texture[] | .[$input] // {"icon": "camera", "frame": 0})
;
def namespace:
@@ -215,6 +164,7 @@ if contains(":") then sub("\\:(.+)"; "") else "minecraft" end
| (if .value.predicate.custom_model_data then .value.predicate.custom_model_data else null end) as $custom_model_data |
{
"item": .key,
"bedrock_icon": bedrocktexture(.key),
"nbt": ({
"Damage": $damage,
"Unbreakable": $unbreakable,
@@ -375,9 +325,6 @@ jq -nc '
"padding": 8,
"num_mip_levels": 4,
"texture_data": {
"gmdl_atlas": {
"textures": "textures/geyser/geyser_custom/gmdl_atlas"
}
}
}
' | sponge ./target/rp/textures/terrain_texture.json
@@ -454,6 +401,12 @@ fi
# generate a fallback texture
convert -size 16x16 xc:\#FFFFFF ./assets/minecraft/textures/0.png
# make sure we crop all mcmeta associated png files
status_message process "Cropping animated textures"
for i in $(find ./assets/**/textures -type f -name "*.mcmeta" | sed 's/\.mcmeta//'); do
convert ${i} -set option:distort:viewport "%[fx:min(w,h)]x%[fx:min(w,h)]" -distort affine "0,0 0,0" ${i}
done
status_message completion "Initial pack setup complete\n"
jq -r '.[] | select(.parent != null) | [.path, .geyserID, .parent] | @tsv | gsub("\\t";",")' config.json | sponge pa.csv
@@ -541,12 +494,6 @@ do
done < pa.csv
# make sure we crop all mcmeta associated png files
status_message process "Cropping animated textures"
for i in $(find ./assets/**/textures -type f -name "*.mcmeta" | sed 's/\.mcmeta//'); do
convert ${i} -set option:distort:viewport "%[fx:min(w,h)]x%[fx:min(w,h)]" -distort affine "0,0 0,0" ${i}
done
status_message process "Compiling final model list"
# get our final 3d model list from the config
model_list=( $(jq -r '.[] | select(.generated == "false") | .path' config.json) )
@@ -554,18 +501,40 @@ model_list=( $(jq -r '.[] | select(.generated == "false") | .path' config.json)
# get our final texture list to be atlased
# get a bash array of all texture files in our resource pack
status_message process "Generating an array of all model PNG files to crosscheck with our atlas"
jq -n '$ARGS.positional' --args $(find ./assets/**/textures -type f -name '*.png') | sponge textures1.temp
jq -n '$ARGS.positional' --args $(find ./assets/**/textures -type f -name '*.png') | sponge all_textures.temp
# get bash array of all texture files listed in our models
status_message process "Generating an array for the master texture atlas"
jq -s 'def namespace: if contains(":") then sub("\\:(.+)"; "") else "minecraft" end; [.[].textures[]?] | unique | map("./assets/" + (. | namespace) + "/textures/" + (. | sub("(.*?)\\:"; "")) + ".png")' ${model_list[@]} | sponge textures2.temp
# find the union of all texture files listed in our models and all texture files in our resource pack
texture_list=( $(jq -s -r '((.[1] - (.[1] - .[0])) + ["./assets/minecraft/textures/0.png"]) | .[]' textures1.temp textures2.temp) )
status_message process "Generating union atlas arrays for all model textures"
jq -s '
def namespace:
if contains(":") then sub("\\:(.+)"; "") else "minecraft" end;
[.[]| [.textures[]] | unique]
| map(map("./assets/" + (. | namespace) + "/textures/" + (. | sub("(.*?)\\:"; "")) + ".png"))
' ${model_list[@]} | sponge union_atlas.temp
jq '
def intersects(a;b): any(a[]; . as $x | any(b[]; . == $x));
# generate our atlas from the final texture list
status_message process "Generating sprite sheet"
spritesheet-js -f json --fullpath ${texture_list[@]} > /dev/null 2>&1
status_message completion "Sprite sheet successfully generated"
mv spritesheet.png ./target/rp/textures/geyser/geyser_custom/gmdl_atlas.png
def mapatlas(set):
(set | unique) as $unique_set
| (map(if intersects(.; $unique_set) then . else empty end) | add + $unique_set | unique) as $new_set
| map(if intersects(.; $new_set) then empty else . end) + [$new_set];
[["./assets/minecraft/textures/0.png"]] +
reduce .[] as $entry ([]; mapatlas($entry))
' union_atlas.temp | sponge union_atlas.temp
total_union_atlas=($(jq -r 'length - 1' union_atlas.temp))
mkdir spritesheet
status_message process "Generating $((1+${total_union_atlas})) sprite sheets..."
for i in $(seq 0 ${total_union_atlas})
do
# find the union of all texture files listed in this atlas and all texture files in our resource pack
texture_list=( $(jq -s --arg index "${i}" -r '(.[1][($index | tonumber)] - .[0] | length > 0) as $fallback_needed | ((.[1][($index | tonumber)] - (.[1][($index | tonumber)] - .[0])) + (if $fallback_needed then ["./assets/minecraft/textures/0.png"] else [] end)) | .[]' all_textures.temp union_atlas.temp) )
status_message process "Generating sprite sheet ${i} of ${total_union_atlas}"
spritesheet-js -f json --name spritesheet/${i} --fullpath ${texture_list[@]} > /dev/null 2>&1
jq --arg atlas_index "${i}" '.texture_data += {("gmdl_atlas_" + $atlas_index): {"textures": ("textures/geyser/geyser_custom/" + $atlas_index)}}' ./target/rp/textures/terrain_texture.json | sponge ./target/rp/textures/terrain_texture.json
done
status_message completion "All sprite sheets generated"
mv spritesheet/*.png ./target/rp/textures/geyser/geyser_custom
# begin conversion
jq -r '.[] | [.path, .geyserID, .generated] | @tsv | gsub("\\t";",")' config.json | sponge all.csv
@@ -577,20 +546,22 @@ do
local gid=${2}
local generated=${3}
# find which texture atlas we will be using if not generated
if [[ ${generated} = "false" ]]
then
local atlas_index=$(jq -r -s 'def namespace: if contains(":") then sub("\\:(.+)"; "") else "minecraft" end; def intersects(a;b): any(a[]; . as $x | any(b[]; . == $x)); (.[0] | [.textures[]] | map("./assets/" + (. | namespace) + "/textures/" + (. | sub("(.*?)\\:"; "")) + ".png")) as $inp | [(.[1] | (map(if intersects(.;$inp) then . else empty end)[])) as $entry | .[1] | to_entries[] | select(.value == $entry).key][0] // 0' ${file} union_atlas.temp)
else
local atlas_index=0
fi
status_message process "Starting conversion of model with GeyserID ${gid}"
jq --slurpfile atlas spritesheet.json --arg generated "${generated}" --arg binding "c.item_slot == 'head' ? 'head' : q.item_slot_to_bone_name(c.item_slot)" --arg model_name "${gid}" -c '
jq --slurpfile atlas spritesheet/${atlas_index}.json --arg generated "${generated}" --arg binding "c.item_slot == 'head' ? 'head' : q.item_slot_to_bone_name(c.item_slot)" --arg model_name "${gid}" -c '
.textures as $texture_list |
def namespace: if contains(":") then sub("\\:(.+)"; "") else "minecraft" end;
def totexture($input): ($texture_list[($input[1:])]? // ([$texture_list[]][0]));
def topath($input): ("./assets/" + ($input | namespace) + "/textures/" + ($input | sub("(.*?)\\:"; "")) + ".png");
def texturedata($input): $atlas[] | .frames | (.[topath(totexture($input))] // ."./assets/minecraft/textures/0.png");
def roundit: (.*10000 | round) / 10000;
def element_array:
if .elements then (.elements | map({
"origin": [((-.to[0] + 8) | roundit), ((.from[1]) | roundit), ((.from[2] - 8) | roundit)],
@@ -624,7 +595,6 @@ do
})
}) | walk( if type == "object" then with_entries(select(.value != null)) else . end)) else {} end
;
def pivot_groups:
if .elements then ((element_array) as $element_array |
[[.elements[].rotation] | unique | .[] | select (.!=null)]
@@ -638,7 +608,6 @@ do
"cubes": [($element_array | .[] | select(.rotation == $i_rot and .pivot == $i_piv))]
}))) else {} end
;
{
"format_version": "1.16.0",
"minecraft:geometry": [{
@@ -793,7 +762,7 @@ do
# generate our bp block definition if this is a 3D item
if [[ ${generated} = false ]]
then
jq -c -n --arg block_material "${block_material}" --arg geyser_id "${gid}" '
jq -c -n --arg atlas_index "${atlas_index}" --arg block_material "${block_material}" --arg geyser_id "${gid}" '
{
"format_version": "1.16.100",
"minecraft:block": {
@@ -803,7 +772,7 @@ do
"components": {
"minecraft:material_instances": {
"*": {
"texture": "gmdl_atlas",
"texture": ("gmdl_atlas_" + $atlas_index),
"render_method": $block_material,
"face_dimming": false,
"ambient_occlusion": false
@@ -845,7 +814,7 @@ do
fi
# generate our rp attachable definition
jq -c -n --arg generated "${generated}" --arg attachable_material "${attachable_material}" --arg v_main "v.main_hand = c.item_slot == 'main_hand';" --arg v_off "v.off_hand = c.item_slot == 'off_hand';" --arg v_head "v.head = c.item_slot == 'head';" --arg model_name "${gid}" '
jq -c -n --arg generated "${generated}" --arg atlas_index "${atlas_index}" --arg attachable_material "${attachable_material}" --arg v_main "v.main_hand = c.item_slot == 'main_hand';" --arg v_off "v.off_hand = c.item_slot == 'off_hand';" --arg v_head "v.head = c.item_slot == 'head';" --arg model_name "${gid}" '
{
"format_version": "1.10.0",
@@ -857,7 +826,7 @@ do
"enchanted": $attachable_material
},
"textures": {
"default": (if $generated == "true" then ("textures/geyser/geyser_custom/" + $model_name) else "textures/geyser/geyser_custom/gmdl_atlas" end),
"default": (if $generated == "true" then ("textures/geyser/geyser_custom/" + $model_name) else ("textures/geyser/geyser_custom/" + $atlas_index) end),
"enchanted": "textures/misc/enchanted_item_glint"
},
"geometry": {
@@ -974,7 +943,7 @@ fi
# cleanup
status_message critical "Deleting scratch files"
rm -rf assets && rm -f pack.mcmeta && rm -f pack.png && rm -f parents.json && rm -f all.csv && rm -f pa.csv && rm -f *.temp && rm -f spritesheet.json
rm -rf spritesheet && rm -rf assets && rm -f pack.mcmeta && rm -f pack.png && rm -f parents.json && rm -f all.csv && rm -f pa.csv && rm -f *.temp && rm -f item_mappings.json && rm -f item_texture.json
#status_message critical "Deleting unused entries from config"
# jq 'map_values(del(.path, .element_parent, .parent, .geyserID))' config.json | sponge config.json
@@ -987,8 +956,9 @@ jq '
{
"name": .key,
"allow_offhand": true,
"icon": (if .value.generated == "false" then .value.item else .key end)
"icon": (if .value.generated == "false" then .value.item else .value.bedrock_icon.icon end)
}
+ (if .value.nbt.generated then {"frame": (.value.bedrock_icon.frame)} else {} end)
+ (if .value.nbt.CustomModelData then {"custom_model_data": (.value.nbt.CustomModelData)} else {} end)
+ (if .value.nbt.Damage then {"damage_predicate": (.value.nbt.Damage)} else {} end)
+ (if .value.nbt.Unbreakable then {"unbreakable": (.value.nbt.Unbreakable)} else {} end)