Advertisement
Guest User

parse_portrait.lua

a guest
Feb 11th, 2016
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.45 KB | None | 0 0
  1. -- A hack to parse player appearance until we get access to inventory slots and
  2. -- identity blocks.
  3. function parse_portrait(entity_portrait, item_database)
  4.   local part_patterns = {
  5.     head = "/humanoid/.+head%.png",
  6.     body = "/humanoid/.+body%.png",
  7.     frontarm = "/humanoid/.+/frontarm%.png",
  8.     hair = "/humanoid/.+/hair/",
  9.     emote = "/humanoid/.+emote%.png",
  10.  
  11.     hat = "/items/.+/head.?%.png",
  12.     chest = "/items/.+/chest.?%.png",
  13.     legs = "/items/.+/pants.?%.png",
  14.     back = "/items/.+/back.?%.png"
  15.   }
  16.  
  17.   local field_patterns = {
  18.     image = "^(.-)%?",
  19.     image_name = "^.-/([^/]+)%.png",
  20.     directives = "%?.+$",
  21.     folder = "^(.-)/[^/]-png",
  22.     frame = "png:(.-)%?",
  23.     gender = "^.-/([^/]+)body%.png",
  24.     parent_folder = "/([^/]-)/[^/]-png",
  25.     species = "/humanoid/([^/]+)"
  26.   }
  27.  
  28.   local function extract_field(part, field)
  29.     if not part then return "" end
  30.     return string.match(part.image, field_patterns[field])
  31.   end
  32.  
  33.   local function extract_part_by_keyword(portrait, keyword)
  34.     if not keyword or keyword == "" then return nil end
  35.  
  36.     local pattern = "/humanoid/.-" .. keyword .. ".-/.-png"
  37.  
  38.     for _, entry in pairs(portrait) do
  39.       if string.match(entry.image, pattern) then return entry end
  40.     end
  41.   end
  42.  
  43.   local function extract_parts(portrait)
  44.     new_table = {}
  45.  
  46.     for part, pattern in pairs(part_patterns) do
  47.       for _, entry in pairs(portrait) do
  48.         if string.match(entry.image, pattern) then
  49.           new_table[part] = entry
  50.           break
  51.         end
  52.       end
  53.     end
  54.  
  55.     return new_table
  56.   end
  57.  
  58.   local function facial_groups(species, gender)
  59.     local species_file = "/species/" .. species .. ".species"
  60.     local species_config = root.assetJson(species_file)
  61.  
  62.     for _, gender_config in ipairs(species_config.genders) do
  63.       if gender_config.name == gender then
  64.         return gender_config.facialHairGroup, gender_config.facialMaskGroup
  65.       end
  66.     end
  67.   end
  68.  
  69.   local function facial_data(portrait, species, gender)
  70.     local hair_group, mask_group = facial_groups(species, gender)
  71.  
  72.     local hair = extract_part_by_keyword(portrait, hair_group)
  73.     local mask = extract_part_by_keyword(portrait, mask_group)
  74.  
  75.     return {
  76.       hair_group = hair_group,
  77.       mask_group = mask_group,
  78.       hair_type = extract_field(hair, "image_name"),
  79.       mask_type = extract_field(mask, "image_name"),
  80.       hair_directives = extract_field(hair, "directives"),
  81.       mask_directives = extract_field(mask, "directives")
  82.     }
  83.   end
  84.  
  85.   local function search_paths(folder, slot, paths)
  86.     sb.logInfo("-> Searching paths for %s in %s...", folder, slot)
  87.     local item_name = paths[slot][folder]
  88.     if item_name then sb.logInfo("--> Found " .. item_name) end
  89.     return item_name
  90.   end
  91.  
  92.   local function search_blueprints(token, slot, blueprints)
  93.     sb.logInfo("-> Searching blueprints for %s in %s...", token, slot)
  94.     local exact_match = nil
  95.     local fuzzy_match = nil
  96.  
  97.     for item,_ in pairs(blueprints[slot .. 'armor']) do
  98.       if item == token then
  99.         sb.logInfo("-> Found exact match: " .. item)
  100.         exact_match = item
  101.       end
  102.  
  103.       if not fuzzy_match and (item:match(token) or token:match(item)) then
  104.         sb.logInfo("-> Found fuzzy match: " .. item)
  105.         fuzzy_match = item
  106.       end
  107.     end
  108.  
  109.     return exact_match, fuzzy_match
  110.   end
  111.  
  112.   local function item_from_path(folder, token, slot)
  113.     local path = folder .. "/" .. token .. "." .. slot
  114.     sb.logInfo("-> Trying to load item from %s...", path)
  115.     local success, item = pcall(function()
  116.       local item_name = root.assetJson(path).itemName
  117.       if root.itemType(item_name) == slot .. "armor" then return item_name end
  118.       return nil
  119.     end)
  120.  
  121.     if success and item then
  122.       sb.logInfo("--> Found %s in %s", item, path)
  123.       return item
  124.     end
  125.  
  126.     return nil
  127.   end
  128.  
  129.   local function recognize_armor(part, slot, database)
  130.     if not part then return { name = "perfectlygenericitem" } end
  131.  
  132.     sb.logInfo("Trying to determine %s item...", slot)
  133.     local directives = extract_field(part, "directives")
  134.     local folder = extract_field(part, "folder")
  135.     local token = string.gsub(extract_field(part, "parent_folder"), "-", "")
  136.  
  137.     local item_name = search_paths(folder, slot, database.paths)
  138.  
  139.     if not item_name then
  140.       local exact_match, fuzzy_match =
  141.         search_blueprints(token, slot, database.blueprints)
  142.  
  143.       item_name =
  144.         exact_match
  145.         or item_from_path(folder, token, slot)
  146.         or fuzzy_match
  147.         or "perfectlygenericitem"
  148.     end
  149.  
  150.     sb.logInfo("Settling for " .. item_name)
  151.     params = { directives = extract_field(part, "directives") }
  152.  
  153.     return { name = item_name, parameters = params }
  154.   end
  155.  
  156.   local function identity_and_costume(portrait, database)
  157.     local parts = extract_parts(portrait)
  158.  
  159.     local species = extract_field(parts.body, "species")
  160.     local gender = extract_field(parts.body, "gender")
  161.     local name = "Clone"
  162.  
  163.     local face = facial_data(portrait, species, gender)
  164.  
  165.     local hair_directives = extract_field(parts.hair, "directives")
  166.     hair_directives = string.gsub(hair_directives, "%?addmask.+$", "")
  167.  
  168.     local data = {
  169.       identity = {
  170.         bodyDirectives = extract_field(parts.body, "directives"),
  171.         emoteDirectives = extract_field(parts.emote, "directives"),
  172.         facialHairDirectives = face.hair_directives,
  173.         facialHairGroup = face.hair_group,
  174.         facialHairType = face.hair_type,
  175.         facialMaskDirectives = face.mask_directives,
  176.         facialMaskGroup = face.mask_group,
  177.         facialMaskType = face.mask_type,
  178.         gender = gender,
  179.         hairDirectives = hair_directives,
  180.         hairGroup = "hair",
  181.         hairType = extract_field(parts.hair, "image_name"),
  182.         name = name,
  183.         personalityArmIdle = extract_field(parts.frontarm, "frame"),
  184.         personalityArmOffset = parts.frontarm.position,
  185.         personalityHeadOffset = parts.head.position,
  186.         personalityIdle = extract_field(parts.body, "frame"),
  187.         species = species
  188.       },
  189.       costume = {
  190.         head = recognize_armor(parts.hat, "head", database),
  191.         chest = recognize_armor(parts.chest, "chest", database),
  192.         legs = recognize_armor(parts.legs, "legs", database),
  193.         back = recognize_armor(parts.back, "back", database),
  194.       }
  195.     }
  196.  
  197.     return data
  198.   end
  199.  
  200.   return identity_and_costume(entity_portrait, item_database)
  201. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement