Skip to content

Commit

Permalink
Make ItemStack rendering properly dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
Pyrofab committed Mar 21, 2024
1 parent 97cd5b6 commit 4c0832e
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 76 deletions.
174 changes: 174 additions & 0 deletions jekyll_plugins/ItemStackTag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
require 'net/http'
require 'uri'

module Ladysnake
class Lang
# Lang files are susceptible to be called by a lot of things, so make a dedicated cache for them
def self.cache
@cache ||= Jekyll::Cache.new("Ladysnake::Lang")
end

def self.fetch(lang_url)
cache.getset(lang_url) do
uri = URI.parse(lang_url)
response = Net::HTTP.get_response(uri)

if response.is_a?(Net::HTTPSuccess)
JSON.parse(response.body)
else
raise "Failed to fetch language data: #{response.code} #{response.message}"
end
end
end
end

def self.parse_args(markup)
args = {}
markup.scan(/(\w+)\s*\=\s*(#{Liquid::QuotedFragment})/o) do |key, value|
args[key] = Liquid::Expression.parse(value)
end
args
end

class ItemStackTag < Liquid::Tag
def self.cache
@cache ||= Jekyll::Cache.new("Ladysnake::ItemStackTag")
end

def cache
self.class.cache
end

def initialize(tag_name, markup, tokens)
super
args = Ladysnake.parse_args(markup)
@item_name = args['item']
@alt_prefix = args['alt_prefix']
@count = args['count']
end

def render(context)
site = context.registers[:site]
data = site.data["minecraft"]["items"]
item_name = context.evaluate(@item_name)
alt_prefix = context.evaluate(@alt_prefix) || ""
count = context.evaluate(@count) || 1
item = data[item_name] || default_data(site.data["mods"]["resource_roots"], item_name)
if item.nil?
item = data["MISSING"]
missing = true
end

"<span class=\"invslot-item invslot-item-image\" data-minetip-title=\"#{item["name"]}\"#{" data-minetip-description=\"#{item_name}\"" if missing}#{' tabindex=0' unless item["link"]}>
#{'<a href="' + item["link"] + '">' if item["link"]}
<img alt=\"#{alt_prefix}#{item["name"]}\" src=\"#{item["icon"]}\" decoding=\"async\" loading=\"lazy\" width=\"32\" height=\"32\">
#{'</a>' if item["link"]}
#{'<span class="invslot-stacksize">' + count.to_s + '</span>' if count > 1}
</span>"
end

private

def default_mod_data(resource_root, namespace, path)
model = fetch_model_data(resource_root, namespace, path)
name = fetch_localized_name(resource_root, namespace, path)
{
'icon' => model,
'name' => name
}
end

def fetch_model_data(resource_root_url, namespace, path)
name = "#{namespace}:#{path}"
json_url = "#{resource_root_url}/assets/#{namespace}/models/item/#{path}.json"

uri = URI.parse(json_url)
response = Net::HTTP.get_response(uri)

if response.is_a?(Net::HTTPSuccess)
model_data = JSON.parse(response.body)
if model_data["parent"].end_with? "item/generated"
texture_namespace, texture_path = model_data["textures"]["layer0"].split(':')
if texture_namespace == namespace
"#{resource_root_url}/assets/#{texture_namespace}/textures/#{texture_path}.png"
else
raise "Texture in external namespace #{texture_namespace} for #{name}"
end
else
raise "Unsupported model parent for #{name}: #{model_data["parent"]}"
end
else
raise "Failed to fetch JSON data for #{name} at #{json_url}: #{response.code} #{response.message}"
end
end

def fetch_localized_name(resource_root_url, namespace, path)
item_name = "#{namespace}:#{path}"
lang_url = "#{resource_root_url}/assets/#{namespace}/lang/en_us.json"

lang_data = Ladysnake::Lang.fetch(lang_url)

localized_name = lang_data["item.#{namespace}.#{path}"]

# If the item name was not found, try the block equivalent
if localized_name.nil?
localized_name = lang_data["block.#{namespace}.#{path}"]
end

# If neither the item nor the block name was found, raise an error
if localized_name.nil?
raise "Localized name not found for #{item_name}"
end

localized_name
end

def default_minecraft_data(item_name)
wiki_name = item_name.gsub(/(_)([a-z])/) { $1 + $2.upcase }.gsub(/^./) { $&.upcase }
url = "https://minecraft.wiki/w/#{wiki_name}"
uri = URI.parse(url)

begin
response = Net::HTTP.get_response(uri)

if response.is_a?(Net::HTTPSuccess)
icon_url = "https://minecraft.wiki/images/Invicon_#{wiki_name}.png"
icon_uri = URI.parse(icon_url)
icon_response = Net::HTTP.get_response(icon_uri)

if icon_response.is_a?(Net::HTTPSuccess)
return {
"name" => wiki_name,
"link" => url,
"icon" => icon_url
}
else
puts "Error: Icon request failed with status code #{icon_response.code} for item #{item_name}"
nil
end
else
puts "Error: Wiki page request failed with status code #{response.code} for item #{item_name}"
nil
end
rescue StandardError => e
puts "Error: #{e.class}: #{e.message} for item #{item_name}"
nil
end
end

def default_data(resource_roots, item_name)
cache.getset(item_name) do
namespace, path = item_name.split(':')
if namespace == "minecraft"
default_minecraft_data(path)
elsif resource_roots.key? namespace
default_mod_data(resource_roots[namespace], namespace, path)
else
nil
end
end
end
end
end

Liquid::Template.register_tag('itemstack', Ladysnake::ItemStackTag)
34 changes: 6 additions & 28 deletions jekyll_plugins/RecipeTag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@

module Ladysnake
class Ingredient
attr_reader :item

def initialize(data)
@item = data["item"]
end

EMPTY = Ingredient.new(Hash["item", "minecraft:air"])

def item
@item
end

def empty?
@item == "minecraft:air"
end
Expand All @@ -23,6 +21,8 @@ def to_s
end

class ShapedRecipe
attr_reader :result, :ingredients, :width, :height

def initialize(result, ingredients, width, height)
@result = result
@ingredients = ingredients
Expand Down Expand Up @@ -74,22 +74,6 @@ def self.parse(data)
ShapedRecipe.new(data["result"], ingredients, width, height)
end

def result
@result
end

def ingredients
@ingredients
end

def width
@width
end

def height
@height
end

def to_3x3_grid
if @width == 3
if @height == 3
Expand All @@ -116,18 +100,12 @@ def to_s
end

class ShapelessRecipe
attr_reader :result, :ingredients

def initialize(result, ingredients)
@result = result
@ingredients = ingredients
end
def result
@result
end

def ingredients
@ingredients
end

def self.parse(data)
ingredients = data["ingredients"].map do |i|
Ingredient.new(i)
Expand Down
37 changes: 6 additions & 31 deletions public/_data/minecraft/items.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
# This file contains data for Minecraft item stack rendering
#
# If an item ID is not present in this file, the plugin will try these steps:
# - If the namespace is "minecraft", it will attempt to guess Minecraft Wiki links for the icon and link
# - If the namespace is listed in ../mods/resource_roots, it will attempt to load data from the corresponding repository
# - Else, it will fall back to the MISSING item data
MISSING:
name: Unknown Item
icon: https://minecraft.wiki/images/Missing_Texture_JE4.png?db402&format=original
"blast:bomb":
name: Bomb
icon: https://raw.githubusercontent.com/Ladysnake/BLAST/1.20/src/main/resources/assets/blast/textures/item/bomb.png
"blast:trigger_bomb":
name: Trigger Bomb
icon: https://raw.githubusercontent.com/Ladysnake/BLAST/1.20/src/main/resources/assets/blast/textures/item/trigger_bomb.png
"blast:golden_bomb":
name: Golden Bomb
icon: https://raw.githubusercontent.com/Ladysnake/BLAST/1.20/src/main/resources/assets/blast/textures/item/golden_bomb.png
"blast:golden_trigger_bomb":
name: Golden Trigger Bomb
icon: https://raw.githubusercontent.com/Ladysnake/BLAST/1.20/src/main/resources/assets/blast/textures/item/golden_trigger_bomb.png
"blast:diamond_bomb":
name: Diamond Bomb
icon: https://raw.githubusercontent.com/Ladysnake/BLAST/1.20/src/main/resources/assets/blast/textures/item/diamond_bomb.png
"blast:diamond_trigger_bomb":
name: Diamond Trigger Bomb
icon: https://raw.githubusercontent.com/Ladysnake/BLAST/1.20/src/main/resources/assets/blast/textures/item/diamond_trigger_bomb.png
"minecraft:diamond":
name: Diamond
link: https://minecraft.wiki/w/Diamond
Expand Down Expand Up @@ -51,16 +39,3 @@ MISSING:
name: String
link: https://minecraft.wiki/w/String
icon: https://minecraft.wiki/images/Invicon_String.png
"minecraft:twisting_vines":
name: Twisting Vines
link: https://minecraft.wiki/w/Twisting_Vines
icon: https://minecraft.wiki/images/Invicon_Twisting_Vines.png
"ratsmischief:leather_rat_pouch":
name: Leather Pouch
icon: https://raw.githubusercontent.com/Ladysnake/RATs-Mischief/2.0/src/main/resources/assets/ratsmischief/textures/item/leather_rat_pouch.png
"ratsmischief:purpur_rat_pouch":
name: Purpur Pouch
icon: https://raw.githubusercontent.com/Ladysnake/RATs-Mischief/2.0/src/main/resources/assets/ratsmischief/textures/item/purpur_rat_pouch.png
"ratsmischief:twisted_rat_pouch":
name: Twisted Pouch
icon: https://raw.githubusercontent.com/Ladysnake/RATs-Mischief/2.0/src/main/resources/assets/ratsmischief/textures/item/twisted_rat_pouch.png
2 changes: 2 additions & 0 deletions public/_data/mods/resource_roots.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
blast: https://raw.githubusercontent.com/Ladysnake/BLAST/1.20/src/main/resources
ratsmischief: https://raw.githubusercontent.com/Ladysnake/Rats-Mischief/2.0/src/main/resources
4 changes: 2 additions & 2 deletions public/_includes/mc/crafting.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
<li class="invslot">
{% if slot %}
{%- capture alt_prefix-%}Ingredient {{ forloop.index }}: {% endcapture -%}
{%- include mc/itemstack.liquid item=slot alt_prefix=alt_prefix -%}
{%- itemstack item=slot alt_prefix=alt_prefix -%}
{% endif %}
</li>
{%- endfor -%}
</{{ grid_tag }}>
<div class="invslot invslot-large">
{%- include mc/itemstack.liquid item=include.result count=include.count alt_prefix="Result: " large="true"-%}
{%- itemstack item=include.result count=include.count alt_prefix="Result: " large=true -%}
</div>
</article>
11 changes: 0 additions & 11 deletions public/_includes/mc/itemstack.liquid

This file was deleted.

2 changes: 1 addition & 1 deletion public/_sass/parts/mc.scss
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
position: relative;
font-size: 20px;

figure & {
figure.recipes & {
font-size: 26.5px;
}
}
Expand Down
23 changes: 22 additions & 1 deletion public/wiki/blast/bomb_table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,25 @@
.header-anchor {
display: none;
}
}
}

.bomb-showcase {
position: relative;
width: 100%;
margin: 0;
display: flex;
flex-direction: column;

& > div {
display: none;
position: absolute;

@include desktop {
display: initial;
}
}

.mcui {
font-size: 21px;
}
}
8 changes: 7 additions & 1 deletion public/wiki/blast/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,13 @@ BLAST mainly focuses on various types of bombs with some common attributes:

Dirt Bombs can be crafted by surrounding normal bombs with 8 Dirt Blocks. Instead of destroying blocks however, they will **create a dirt pile wherever they explode.** As such, they are a great counter to creeper holes!

![Dirt Bombs](DirtBombs.png)
<figure class="bomb-showcase">
<div style="top:2em; left:0">
{% recipe dirt_bomb.json %}
{% recipe dirt_trigger_bomb.json %}
</div>
<img src="./DirtBombs.png" alt="Dirt Bombs"/>
</figure>

### Pearl Bombs

Expand Down
2 changes: 1 addition & 1 deletion public/wiki/rats-mischief/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Rat pouches can be used to quickly gather rats back. Using a pouch on a rat will
Pouches can be crafted like bundles with leather, twisted vines and popped chorus fruit, to produce respectively pouches with a capacity of 5, 10 and 20 rats.
Rats stored in Pouches won't age, meaning they will keep status effects, health, their variant and names.

<figure>
<figure class="recipes">
{% recipe leather_rat_pouch.json %}
{% recipe twisted_rat_pouch.json %}
{% recipe purpur_rat_pouch.json %}
Expand Down

0 comments on commit 4c0832e

Please sign in to comment.