Merge pull request 'Remove 2D preview + fix enchanting overlay by AFCMS' (#311) from MrRar/MineClone5:armor2d into master

Reviewed-on: MineClone5/MineClone5#311
This commit is contained in:
kay27 2022-07-04 01:38:55 +00:00
commit 7640edabcc
40 changed files with 314 additions and 89 deletions

View File

@ -339,14 +339,6 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size,
if name == "inv" then
inv_bg = "crafting_inventory_creative_survival.png"
-- Show armor and player image
local player_preview
if minetest.settings:get_bool("3d_player_preview", true) then
player_preview = mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "")
else
player_preview = "image[3.9,1.4;1.2333,2.4666;"..mcl_player.player_get_preview(player).."]"
end
-- Background images for armor slots (hide if occupied)
local armor_slot_imgs = ""
local inv = player:get_inventory()
@ -386,8 +378,7 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size,
armor_slot_imgs..
-- player preview
player_preview..
mcl_player.get_player_formspec_model(player, 3.9, 1.4, 1.2333, 2.4666, "")..
-- crafting guide button
"image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]"..
"tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]"..

View File

@ -61,14 +61,6 @@ local function set_inventory(player, armor_change_only)
inv:set_width("craft", 2)
inv:set_size("craft", 4)
-- Show armor and player image
local player_preview
if minetest.settings:get_bool("3d_player_preview", true) then
player_preview = mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "")
else
player_preview = "image[1.1,0.2;2,4;"..mcl_player.player_get_preview(player).."]"
end
local armor_slots = {"helmet", "chestplate", "leggings", "boots"}
local armor_slot_imgs = ""
for a=1,4 do
@ -83,7 +75,7 @@ local function set_inventory(player, armor_change_only)
local form = "size[9,8.75]"..
"background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]"..
player_preview..
mcl_player.get_player_formspec_model(player, 1.0, 0.0, 2.25, 4.5, "")..
--armor
"list[current_player;armor;0,0;1,1;1]"..
"list[current_player;armor;0,1;1,1;2]"..

288
mods/ITEMS/mcl_armor/API.md Normal file
View File

@ -0,0 +1,288 @@
# mcl_armor
This mod implements the ability of registering armors.
## Registering an Armor Set
The `mcl_armor.register_set()` function aims to simplify the process of registering a full set of armor.
This function register four pieces of armor (head, torso, leggings, feets) based on a definition table:
```lua
mcl_armor.register_set({
--name of the armor material (used for generating itemstrings)
name = "dummy_armor",
--description of the armor material
--do NOT translate this string, it will be concatenated will each piece of armor's description and result will be automatically fetched from your mod's translation files
description = "Dummy Armor",
--overide description of each armor piece
--do NOT localize this string
descriptions = {
head = "Cap", --default: "Helmet"
torso = "Tunic", --default: "Chestplate"
legs = "Pants", --default: "Leggings"
feet = "Shoes", --default: "Boots"
},
--this is used to calculate each armor piece durability with the minecraft algorithm
--head durability = durability * 0.6857 + 1
--torso durability = durability * 1.0 + 1
--legs durability = durability * 0.9375 + 1
--feet durability = durability * 0.8125 + 1
durability = 80,
--this is used then you need to specify the durability of each piece of armor
--this field have the priority over the durability one
--if the durability of some pieces of armor isn't specified in this field, the durability field will be used insteed
durabilities = {
head = 200,
torso = 500,
legs = 400,
feet = 300,
},
--this define how good enchants you will get then enchanting one piece of the armor in an enchanting table
--if set to zero or nil, the armor will not be enchantable
enchantability = 15,
--this define how much each piece of armor protect the player
--these points will be shown in the HUD (chestplate bar above the health bar)
points = {
head = 1,
torso = 3,
legs = 2,
feet = 1,
},
--this attribute reduce strong damage even more
--See https://minecraft.fandom.com/wiki/Armor#Armor_toughness for more explanations
--default: 0
toughness = 2,
--this field is used to specify some items groups that will be added to each piece of armor
--please note that some groups do NOT need to be added by hand, because they are already handeled by the register function:
--(armor, combat_armor, armor_<element>, combat_armor_<element>, mcl_armor_points, mcl_armor_toughness, mcl_armor_uses, enchantability)
groups = {op_armor = 1},
--specify textures that will be overlayed on the entity wearing the armor
--these fields have default values and its recommanded to keep the code clean by just using the default name for your textures
textures = {
head = "dummy_texture.png", --default: "<modname>_helmet_<material>.png"
torso = "dummy_texture.png", --default: "<modname>_chestplate_<material>.png"
legs = "dummy_texture.png", --default: "<modname>_leggings_<material>.png"
feet = "dummy_texture.png", --default: "<modname>_boots_<material>.png"
},
--you can also define these fields as functions, that will be called each time the API function mcl_armor.update(obj) is called (every time you equip/unequip some armor piece, take damage, and more)
--note that the enchanting overlay will not appear unless you implement it in the function
--this allow to make armors where the textures change whitout needing to register many other armors with different textures
textures = {
head = function(obj, itemstack)
if mcl_enchanting.is_enchanted(itemstack) then
return "dummy_texture.png^"..mcl_enchanting.overlay
else
return "dummy_texture.png"
end
end,
},
--inventory textures aren't definable using a table similar to textures or previews
--you are forced to use the default texture names which are:
--head: "<modname>_inv_helmet_<material>.png
--torso: "<modname>_inv_chestplate_<material>.png
--legs: "<modname>_inv_leggings_<material>.png
--feet: "<modname>_inv_boots_<material>.png
--this callback table allow you to define functions that will be called each time an entity equip an armor piece or the mcl_armor.on_equip() function is called
--the functions accept two arguments: obj and itemstack
on_equip_callbacks = {
head = function(obj, itemstack)
--do stuff
end,
},
--this callback table allow you to define functions that will be called each time an entity unequip an armor piece or the mcl_armor.on_unequip() function is called
--the functions accept two arguments: obj and itemstack
on_unequip_callbacks = {
head = function(obj, itemstack)
--do stuff
end,
},
--this callback table allow you to define functions that will be called then an armor piece break
--the functions accept one arguments: obj
--the itemstack isn't sended due to how minetest handle items which have a zero durability
on_break_callbacks = {
head = function(obj)
--do stuff
end,
},
--this is used to generate automaticaly armor crafts based on each element type folowing the regular minecraft pattern
--if set to nil no craft will be added
craft_material = "mcl_mobitems:leather",
--this is used to generate cooking crafts for each piece of armor
--if set to nil no craft will be added
cook_material = "mcl_core:gold_nugget", --cooking any piece of this armor will output a gold nugged
--this is used for allowing each piece of the armor to be repaired by using an anvil with repair_material as aditionnal material
--it basicaly set the _repair_material item field of each piece of the armor
--if set to nil no repair material will be added
repair_material = "mcl_core:iron_ingot",
})
```
## Creating an Armor Piece
If you don't want to register a full set of armor, then you will need to manually register your own single item.
```lua
minetest.register_tool("dummy_mod:random_armor", {
description = S("Random Armor"),
--these two item fields are used for ingame documentation
--the mcl_armor.longdesc and mcl_armor.usage vars contains the basic usage and purpose of a piece of armor
--these vars may not be enough for that you want to do, so you may add some extra informations like that:
--_doc_items_longdesc = mcl_armor.longdesc.." "..S("Some extra informations.")
_doc_items_longdesc = mcl_armor.longdesc,
_doc_items_usagehelp = mcl_armor.usage,
--this field is similar to any item definition in minetest
--it just set the image shown then the armor is dropped as an item or inside an inventory
inventory_image = "mcl_armor_inv_elytra.png",
--this field is used by minetest internally and also by some helper functions
--in order for the tool to be shown is the right creative inventory tab, the right groups should be added
--"mcl_armor_uses" is required to give your armor a durability
--in that case, the armor can be worn by 10 points before breaking
--if you want the armor to be enchantable, you should also add the "enchantability" group, with the highest number the better enchants you can apply
groups = {armor = 1, non_combat_armor = 1, armor_torso = 1, non_combat_torso = 1, mcl_armor_uses = 10},
--this table is used by minetest for seraching item specific sounds
--the _mcl_armor_equip and _mcl_armor_unequip are used by the armor implementation to play sounds on equip and unequip
--note that you don't need to provide any file extention
sounds = {
_mcl_armor_equip = "mcl_armor_equip_leather",
_mcl_armor_unequip = "mcl_armor_unequip_leather",
},
--these fields should be initialised like that in most cases
--mcl_armor.equip_on_use is a function that try to equip the piece of armor you have in hand inside the right armor slot if the slot is empty
on_place = mcl_armor.equip_on_use,
on_secondary_use = mcl_armor.equip_on_use,
--this field define that the tool is ACTUALLY an armor piece and in which armor slot you can put it
--it should be set to "head", "torso", "legs" or "feet"
_mcl_armor_element = "torso",
--this field is used to provide the texture that will be overlayed on the object (player or mob) skin
--this field can be a texture name or a function that will be called each time the mcl_armor.update(obj) function is called
--see the mcl_armor.register_set() documentation for more explanations
_mcl_armor_texture = "mcl_armor_elytra.png"
--callbacks
--see the mcl_armor.register_set() documentation for more explanations
_on_equip = function(obj, itemstack)
end,
_on_unequip = function(obj, itemstack)
end,
_on_break = function(obj)
end,
})
```
## Interacting with Armor of an Entity
Mods may want to interact with armor of an entity.
Most global functions not described here may not be stable or may be for internal use only.
You can equip a piece of armor on an entity inside a mod by using `mcl_armor.equip()`.
```lua
--itemstack: an itemstack containing the armor piece to equip
--obj: the entity you want to equip the armor on
--swap: boolean, force equiping the armor piece, even if the entity already have one of the same type
mcl_armor.equip(itemstack, obj, swap)
```
You can update the entity apparence by using `mcl_armor.update()`.
This function put the armor overlay on the object's base texture.
If the object is player it will update his displayed armor points count in HUD.
This function will work both on players and mobs.
```lua
--obj: the entity you want the apparence to be updated
mcl_armor.update(obj)
```
## Handling Enchantments
Armors can be enchanted in most cases.
The enchanting part of MineClone2 is separated from the armor part, but closely linked.
Existing armor enchantments in Minecraft improve most of the time how the armor protect the entity from damage.
The `mcl_armor.register_protection_enchantment()` function aims to simplificate the creation of such enchants.
```lua
mcl_armor.register_protection_enchantment({
--this field is the id that will be used for registering enchanted book and store the enchant inside armor metadata.
--(his internal name)
id = "magic_protection",
--visible name of the enchant
--this field is used as the name of registered enchanted book and inside armor tooltip
--translation should be added
name = S("Magic Protection"),
--this field is used to know that the enchant currently do
--translation should be added
description = S("Reduces magic damage."),
--how many levels can the enchant have
--ex: 4 => I, II, III, IV
--default: 4
max_level = 4,
--which enchants this enchant will not be compatible with
--each of these values is a enchant id
incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true},
--how much will the enchant consume from the enchantability group of the armor item
--default: 5
weight = 5,
--false => the enchant can be obtained in an enchanting table
--true => the enchant isn't obtainable in the enchanting table
--is true, you will probably need to implement some ways to obtain it
--even it the field is named "treasure", it will be no way to find it
--default: false
treasure = false,
--how much will damage be reduced
--see Minecraft Wiki for more informations
--https://minecraft.gamepedia.com/Armor#Damage_protection
--https://minecraft.gamepedia.com/Armor#Enchantments
factor = 1,
--restrict damage to one type
--allow the enchant to only protect of one type of damage
damage_type = "magic",
--restrict damage to one category
--allow to protect from many type of damage at once
--this is much less specific than damage_type and also much more customisable
--the "is_magic" flag is used in the "magic", "dragon_breath", "wither_skull" and "thorns" damage types
--you can checkout the mcl_damage source code for a list of availlable damage types and associated flags
--but be warned that mods can register additionnal damage types
damage_flag = "is_magic",
})
```

View File

@ -94,7 +94,6 @@ function mcl_armor.register_set(def)
local on_unequip_callbacks = def.on_unequip_callbacks or {}
local on_break_callbacks = def.on_break_callbacks or {}
local textures = def.textures or {}
local previews = def.previews or {}
local durabilities = def.durabilities or {}
local element_groups = def.element_groups or {}
@ -134,8 +133,7 @@ function mcl_armor.register_set(def)
_on_break = on_break_callbacks[name] or def.on_break,
_mcl_armor_element = name,
_mcl_armor_texture = textures[name] or modname .. "_" .. itemname .. ".png",
_mcl_armor_preview = previews[name] or modname .. "_" .. itemname .. "_preview.png",
_mcl_upgradable = def.upgradable,
_mcl_upgradable = def.upgradable
})
if def.craft_material then
@ -222,17 +220,6 @@ function mcl_armor.update(obj)
end
end
local preview = def._mcl_armor_preview
if obj:is_player() and preview then
if type(preview) == "function" then
preview = preview(obj, itemstack)
end
if preview then
info.preview = "(player.png^[opacity:0^" .. def._mcl_armor_preview .. ")" .. (info.preview and "^" .. info.preview or "" )
end
end
info.points = info.points + minetest.get_item_group(itemname, "mcl_armor_points")
local mob_range_mob = def._mcl_armor_mob_range_mob
@ -255,8 +242,6 @@ function mcl_armor.update(obj)
info.texture = info.texture or "blank.png"
if obj:is_player() then
info.preview = info.preview or "blank.png"
mcl_armor.update_player(obj, info)
else
local luaentity = obj:get_luaentity()

View File

@ -63,7 +63,7 @@ mcl_player.player_register_model("mcl_armor_character_female.b3d", {
})
function mcl_armor.update_player(player, info)
mcl_player.player_set_armor(player, info.texture, info.preview)
mcl_player.player_set_armor(player, info.texture)
local meta = player:get_meta()
meta:set_int("mcl_armor:armor_points", info.points)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

View File

@ -271,11 +271,10 @@ function mcl_enchanting.initialize()
new_def.groups.not_in_craft_guide = 1
new_def.groups.enchanted = 1
if new_def._mcl_armor_texture and not type(new_def._mcl_armor_texture) == "function" then
new_def._mcl_armor_texture = new_def._mcl_armor_texture .. mcl_enchanting.overlay
end
if new_def._mcl_armor_preview and not type(new_def._mcl_armor_preview) == "function" then
new_def._mcl_armor_preview = new_def._mcl_armor_preview .. mcl_enchanting.overlay
if new_def._mcl_armor_texture then
if type(new_def._mcl_armor_texture) == "string" then
new_def._mcl_armor_texture = new_def._mcl_armor_texture .. mcl_enchanting.overlay
end
end
new_def._mcl_enchanting_enchanted_tool = new_name

View File

@ -120,7 +120,6 @@ pumpkin_face_base_def._mcl_armor_mob_range_factor = 0
pumpkin_face_base_def._mcl_armor_mob_range_mob = "mobs_mc:enderman"
pumpkin_face_base_def._mcl_armor_element = "head"
pumpkin_face_base_def._mcl_armor_texture = "mcl_farming_pumpkin_face.png"
pumpkin_face_base_def._mcl_armor_preview = "mcl_farming_pumpkin_face_preview.png"
if minetest.get_modpath("mcl_armor") then
local pumpkin_hud = {}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 B

View File

@ -113,7 +113,6 @@ local function addhead(name, texture, desc, longdesc, rangemob, rangefactor)
_mcl_armor_mob_range_factor = rangefactor,
_mcl_armor_element = "head",
_mcl_armor_texture = "mcl_heads_" .. name .. ".png",
_mcl_armor_preview = "mcl_heads_" .. name .. "_preview.png",
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 B

View File

@ -95,31 +95,16 @@ local function set_texture(player, index, texture)
player:set_properties({textures = textures})
end
local function set_preview(player, field, preview)
player:get_meta():set_string("mcl_player:" .. field .. "_preview", preview)
end
function mcl_player.player_set_skin(player, texture, preview)
function mcl_player.player_set_skin(player, texture)
set_texture(player, 1, texture)
set_preview(player, "skin", preview)
end
function mcl_player.player_set_armor(player, texture, preview)
function mcl_player.player_set_armor(player, texture)
set_texture(player, 2, texture)
set_preview(player, "armor", preview)
end
function mcl_player.player_get_preview(player)
local preview = player:get_meta():get_string("mcl_player:skin_preview")
if preview == "" then
preview = "player.png"
end
local armor_preview = player:get_meta():set_string("mcl_player:armor_preview")
if armor_preview ~= "" then
preview = preview .. "^" .. armor_preview
end
return preview
function mcl_player.player_set_wielditem(player, texture)
set_texture(player, 3, texture)
end
function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname)

4
mods/PLAYER/mcl_skins/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
!textures/mcl_skins_character_1.png
textures/mcl_skins_character_*
!meta/mcl_skins_character_1.txt
meta/mcl_skins_character_*

View File

@ -3,7 +3,7 @@
local modname = minetest.get_current_modname()
mcl_skins = {
skins = {}, list = {}, previews = {}, meta = {}, has_preview = {},
skins = {}, list = {}, meta = {},
modpath = minetest.get_modpath(modname),
skin_count = 0, -- counter of _custom_ skins (all skins except character.png)
}
@ -18,10 +18,8 @@ while true do
if id == 0 then
skin = "character"
mcl_skins.has_preview[id] = true
else
skin = "mcl_skins_character_" .. id
local preview = "mcl_skins_player_" .. id
-- Does skin file exist?
f = io.open(mcl_skins.modpath .. "/textures/" .. skin .. ".png")
@ -31,20 +29,12 @@ while true do
break
end
f:close()
-- Does skin preview file exist?
local file_preview = io.open(mcl_skins.modpath .. "/textures/" .. preview .. ".png")
if file_preview == nil then
minetest.log("warning", "[mcl_skins] Player skin #"..id.." does not have preview image (player_"..id..".png)")
mcl_skins.has_preview[id] = false
else
mcl_skins.has_preview[id] = true
file_preview:close()
end
end
mcl_skins.list[id] = skin
local metafile
-- does metadata exist for that skin file ?
if id == 0 then
metafile = "mcl_skins_character.txt"
@ -89,12 +79,11 @@ function mcl_skins.set_player_skin(player, skin_id)
return false
end
local playername = player:get_player_name()
local skin, preview
local skin
if skin_id == nil or type(skin_id) ~= "number" or skin_id < 0 or skin_id > mcl_skins.skin_count then
return false
elseif skin_id == 0 then
skin = "character"
preview = "player"
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
else
skin = "mcl_skins_character_" .. tostring(skin_id)
@ -104,16 +93,9 @@ function mcl_skins.set_player_skin(player, skin_id)
else
mcl_player.player_set_model(player, "mcl_armor_character.b3d")
end
if mcl_skins.has_preview[skin_id] then
preview = "mcl_skins_player_" .. tostring(skin_id)
else
-- Fallback preview image if preview image is missing
preview = "mcl_skins_player_dummy"
end
end
--local skin_file = skin .. ".png"
mcl_skins.skins[playername] = skin
mcl_skins.previews[playername] = preview
player:get_meta():set_string("mcl_skins:skin_id", tostring(skin_id))
mcl_skins.update_player_skin(player)
if has_mcl_inventory then
@ -131,7 +113,7 @@ function mcl_skins.update_player_skin(player)
return
end
local playername = player:get_player_name()
mcl_player.player_set_skin(player, mcl_skins.skins[playername] .. ".png", mcl_skins.previews[playername] .. ".png")
mcl_player.player_set_skin(player, mcl_skins.skins[playername] .. ".png")
end
-- load player skin on join
@ -259,7 +241,11 @@ function mcl_skins.show_formspec(playername)
formspec = formspec .. ";" .. selected .. ";false]"
formspec = formspec .. "image[0,0;1.35,2.7;" .. mcl_skins.previews[playername] .. ".png]"
local player = minetest.get_player_by_name(playername)
if player then
--maybe the function could accept both player object and player name?
formspec = formspec .. mcl_player.get_player_formspec_model(player, 0, 0, 1.35, 2.7, "mcl_skins:skin_select")
end
if meta then
if meta.name and meta.name ~= "" then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

View File

@ -101,9 +101,6 @@ fire_animation_frames (Fire Animation Frames) int 8
# Whether to animate chests when open / close
animated_chests (Animated chests) bool true
# Whether to preview the player in inventory in 3D (requires Minetest 5.4)
3d_player_preview (3D Player preview) bool true
# The maximum number of boss bars to simultaniously display on the screen
max_bossbars (Maximum Boss bars) int 5