Changeset 25223
- Timestamp:
- Apr 9, 2021, 5:43:50 PM (3 years ago)
- Location:
- ps/trunk
- Files:
-
- 2 added
- 2 deleted
- 22 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/binaries/data/mods/public/simulation/templates/mixins/hoplite.xml
r25221 r25223 1 <?xml version="1.0" encoding="utf-8" ?>2 <Entity parent="template_unit_hero_infantry_spearman">1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity> 3 3 <Identity> 4 4 <Formations datatype="tokens"> -
ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_infantry.xml
r25174 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit">2 <Entity parent="template_unit"> 3 3 <Attack> 4 4 <Capture> … … 17 17 </Slaughter> 18 18 </Attack> 19 <Builder>20 <Rate>1.0</Rate>21 <Entities datatype="tokens">22 structures/{civ}/civil_centre23 structures/{civ}/crannog24 structures/{civ}/military_colony25 structures/{civ}/house26 structures/{civ}/apartment27 structures/{civ}/storehouse28 structures/{civ}/farmstead29 structures/{civ}/field30 structures/{civ}/corral31 structures/{civ}/dock32 structures/{civ}/barracks33 structures/{civ}/stable34 structures/{civ}/elephant_stable35 structures/{civ}/arsenal36 structures/{civ}/forge37 structures/{civ}/temple38 structures/{civ}/market39 structures/{civ}/outpost40 structures/{civ}/sentry_tower41 structures/{civ}/defense_tower42 structures/{civ}/fortress43 structures/wallset_palisade44 structures/{civ}/wallset_siege45 structures/{civ}/wallset_stone46 structures/{civ}/theater47 structures/{civ}/wonder48 </Entities>49 </Builder>50 19 <Cost> 51 20 <BuildTime>12</BuildTime> … … 63 32 <GenericName>Infantry</GenericName> 64 33 <Classes datatype="tokens">Human CitizenSoldier</Classes> 65 <VisibleClasses datatype="tokens">Citizen BuilderWorker Soldier Infantry</VisibleClasses>34 <VisibleClasses datatype="tokens">Citizen Worker Soldier Infantry</VisibleClasses> 66 35 <Rank>Basic</Rank> 67 36 </Identity> -
ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
r25174 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support">2 <Entity parent="template_unit_support"> 3 3 <Attack> 4 4 <Melee> … … 19 19 </Slaughter> 20 20 </Attack> 21 <Builder>22 <Rate>1.0</Rate>23 <Entities datatype="tokens">24 structures/{civ}/civil_centre25 structures/{civ}/crannog26 structures/{civ}/military_colony27 structures/{civ}/house28 structures/{civ}/apartment29 structures/{civ}/storehouse30 structures/{civ}/farmstead31 structures/{civ}/field32 structures/{civ}/corral33 structures/{civ}/dock34 structures/{civ}/barracks35 structures/{civ}/stable36 structures/{civ}/elephant_stable37 structures/{civ}/arsenal38 structures/{civ}/forge39 structures/{civ}/temple40 structures/{civ}/market41 structures/{civ}/outpost42 structures/{civ}/sentry_tower43 structures/{civ}/defense_tower44 structures/{civ}/fortress45 structures/wallset_palisade46 structures/{civ}/wallset_siege47 structures/{civ}/wallset_stone48 structures/{civ}/theater49 structures/{civ}/wonder50 </Entities>51 </Builder>52 21 <Cost> 53 22 <BuildTime>9</BuildTime> … … 64 33 <SelectionGroupName>template_unit_support_female_citizen</SelectionGroupName> 65 34 <Classes datatype="tokens">FemaleCitizen</Classes> 66 <VisibleClasses datatype="tokens">Citizen BuilderWorker</VisibleClasses>35 <VisibleClasses datatype="tokens">Citizen Worker</VisibleClasses> 67 36 <Formations disable=""/> 68 37 </Identity> -
ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_support_slave.xml
r25174 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_support">2 <Entity parent="template_unit_support"> 3 3 <Builder> 4 4 <Rate>0.5</Rate> 5 <Entities datatype="tokens">6 structures/{civ}/civil_centre7 structures/{civ}/crannog8 structures/{civ}/military_colony9 structures/{civ}/house10 structures/{civ}/apartment11 structures/{civ}/storehouse12 structures/{civ}/farmstead13 structures/{civ}/field14 structures/{civ}/corral15 structures/{civ}/dock16 structures/{civ}/barracks17 structures/{civ}/stable18 structures/{civ}/elephant_stable19 structures/{civ}/arsenal20 structures/{civ}/forge21 structures/{civ}/temple22 structures/{civ}/market23 structures/{civ}/outpost24 structures/{civ}/sentry_tower25 structures/{civ}/defense_tower26 structures/{civ}/fortress27 structures/wallset_palisade28 structures/{civ}/wallset_siege29 structures/{civ}/wallset_stone30 structures/{civ}/theater31 structures/{civ}/wonder32 </Entities>33 5 </Builder> 34 6 <Cost> … … 47 19 <SelectionGroupName>template_unit_support_slave</SelectionGroupName> 48 20 <Tooltip>Gatherer with a finite life span. Bonused at mining and lumbering.</Tooltip> 49 <VisibleClasses datatype="tokens"> BuilderWorker Slave</VisibleClasses>21 <VisibleClasses datatype="tokens">Worker Slave</VisibleClasses> 50 22 </Identity> 51 23 <Loot> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/champion_infantry.xml
r24216 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_champion_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Civ>athen</Civ> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/hero_pericles.xml
r24216 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_hero_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Auras datatype="tokens"> 4 4 units/heroes/athen_hero_pericles_1 -
ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/infantry_spearman_b.xml
r24687 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_infantry_melee_spearman_hoplite">2 <Entity parent=""> 3 3 <Builder> 4 4 <Entities datatype="tokens"> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/champion_infantry.xml
r24216 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_champion_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Civ>cart</Civ> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_spearman_b.xml
r24216 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_infantry_melee_spearman_hoplite">2 <Entity parent=""> 3 3 <Builder> 4 4 <Entities datatype="tokens"> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/champion_infantry_spearman.xml
r24657 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_champion_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Civ>mace</Civ> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/kardakes_hoplite.xml
r24216 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_champion_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Civ>pers</Civ> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_spearman_merc_b.xml
r24330 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_infantry_melee_spearman_hoplite">2 <Entity parent=""> 3 3 <Builder> 4 4 <Entities datatype="tokens"> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/samnite_spearman.xml
r22824 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_champion_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <VisibleClasses datatype="tokens">Mercenary</VisibleClasses> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_spearman_b.xml
r24687 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_infantry_melee_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Civ>sele</Civ> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/champion_infantry_spear.xml
r24216 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_champion_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Civ>spart</Civ> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/hero_agis.xml
r24474 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_hero_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Civ>spart</Civ> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/hero_leonidas.xml
r24216 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_hero_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Auras datatype="tokens"> 4 4 units/heroes/spart_hero_leonidas -
ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/infantry_spearman_b.xml
r24687 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_infantry_melee_spearman_hoplite">2 <Entity parent=""> 3 3 <Builder> 4 4 <Entities datatype="tokens"> -
ps/trunk/binaries/data/mods/public/simulation/templates/units/thebes_sacred_band_hoplitai.xml
r21975 r25223 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <Entity parent=" template_unit_champion_infantry_spearman_hoplite">2 <Entity parent=""> 3 3 <Identity> 4 4 <Lang>greek</Lang> -
ps/trunk/source/ps/TemplateLoader.cpp
r23704 r25223 1 /* Copyright (C) 202 0Wildfire Games.1 /* Copyright (C) 202 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * … … 30 30 static CParamNode NULL_NODE(false); 31 31 32 bool CTemplateLoader::LoadTemplateFile( const std::string& templateName, int depth)32 bool CTemplateLoader::LoadTemplateFile(, int depth) 33 33 { 34 // If this file was already loaded, we don't need to do anything 35 if (m_TemplateFileData.find(templateName) != m_TemplateFileData.end()) 34 // Handle special case "actor|foo", which does not load 'foo' at all, just uses the name. 35 if (templateName.compare(0, 6, "actor|") == 0) 36 { 37 ConstructTemplateActor(templateName.substr(6), node); 36 38 return true; 37 39 } 38 40 // Handle infinite loops more gracefully than running out of stack space and crashing 39 41 if (depth > 100) 40 42 { 41 LOGERROR("Probable infinite inheritance loop in entity template '%s'", templateName.c_str());43 LOGERROR("Probable infinite inheritance loop in entity template '%s'", )); 42 44 return false; 43 45 } 44 46 45 // Handle special case "actor|foo"46 if ( templateName.find("actor|") == 0)47 48 if () 47 49 { 48 ConstructTemplateActor(templateName.substr(6), m_TemplateFileData[templateName]); 50 // 'foo|bar' pattern: 'bar' is treated as the parent of 'foo'. 51 if (!LoadTemplateFile(node, templateName.substr(pos + 1), false, depth + 1)) 52 return false; 53 if (!LoadTemplateFile(node, templateName.substr(0, pos), true, depth + 1)) 54 return false; 49 55 return true; 50 56 } 51 57 52 // Handle special case "bar|foo" 53 size_t pos = templateName.find_first_of('|'); 54 if (pos != std::string::npos) 55 { 56 std::string prefix = templateName.substr(0, pos); 57 std::string baseName = templateName.substr(pos+1); 58 // Load the data we need to apply on the node. This data may contain special modifiers, 59 // such as filters, merges, multiplying the parent values, etc. Applying it to paramnode is destructive. 60 // Find the XML file to load - by default, this assumes the files reside in 'special/filter'. 61 // If not found there, it will be searched for in 'mixins/', then from the root. 62 // The reason for this order is that filters are used at runtime, mixins at load time. 63 std::wstring wtempName = wstring_from_utf8(std::string(templateName) + ".xml"); 64 VfsPath path = VfsPath(TEMPLATE_ROOT) / L"special" / L"filter" / wtempName; 65 if (!VfsFileExists(path)) 66 path = VfsPath(TEMPLATE_ROOT) / L"mixins" / wtempName; 67 if (!VfsFileExists(path)) 68 path = VfsPath(TEMPLATE_ROOT) / wtempName; 58 69 59 if (!LoadTemplateFile(baseName, depth+1))60 {61 LOGERROR("Failed to load entity template '%s'", baseName.c_str());62 return false;63 }64 65 VfsPath path = VfsPath(TEMPLATE_ROOT) / L"special" / L"filter" / wstring_from_utf8(prefix + ".xml");66 if (!VfsFileExists(path))67 {68 LOGERROR("Invalid subset '%s'", prefix.c_str());69 return false;70 }71 72 CXeromyces xero;73 PSRETURN ok = xero.Load(g_VFS, path);74 if (ok != PSRETURN_OK)75 return false; // (Xeromyces already logged an error with the full filename)76 77 m_TemplateFileData[templateName] = m_TemplateFileData[baseName];78 CParamNode::LoadXML(m_TemplateFileData[templateName], xero, path.string().c_str());79 return true;80 }81 82 // Normal case: templateName is an XML file:83 84 VfsPath path = VfsPath(TEMPLATE_ROOT) / wstring_from_utf8(templateName + ".xml");85 70 CXeromyces xero; 86 71 PSRETURN ok = xero.Load(g_VFS, path); … … 88 73 return false; // (Xeromyces already logged an error with the full filename) 89 74 75 90 76 int attr_parent = xero.GetAttributeID("parent"); 91 77 CStr parentName = xero.GetRoot().GetAttributes().GetNamedItem(attr_parent); 92 if (!parentName.empty()) 93 { 94 // To prevent needless complexity in template design, we don't allow |-separated strings as parents 95 if (parentName.find('|') != parentName.npos) 96 { 97 LOGERROR("Invalid parent '%s' in entity template '%s'", parentName.c_str(), templateName.c_str()); 98 return false; 99 } 78 if (!parentName.empty() && !LoadTemplateFile(node, parentName, compositing, depth + 1)) 79 return false; 100 80 101 // Ensure the parent is loaded 102 if (!LoadTemplateFile(parentName, depth+1)) 103 { 104 LOGERROR("Failed to load parent '%s' of entity template '%s'", parentName.c_str(), templateName.c_str()); 105 return false; 106 } 107 108 CParamNode& parentData = m_TemplateFileData[parentName]; 109 110 // Initialise this template with its parent 111 m_TemplateFileData[templateName] = parentData; 112 } 113 114 // Load the new file into the template data (overriding parent values) 115 CParamNode::LoadXML(m_TemplateFileData[templateName], xero, wstring_from_utf8(templateName).c_str()); 116 81 // Load the new file into the template data (overriding parent values). 82 // TODO: error handling. 83 CParamNode::LoadXML(node, xero); 117 84 return true; 118 85 } … … 125 92 VfsPath pathstem = pathname.ChangeExtension(L""); 126 93 // Strip the root from the path 127 std::wstring name = pathstem.string().substr(ARRAY_SIZE(TEMPLATE_ROOT)-1);94 std::wstring name = pathstem.string().substr(ARRAY_SIZE(TEMPLATE_ROOT)-1); 128 95 129 96 // We want to ignore template_*.xml templates, since they should never be built in the editor … … 131 98 return INFO::OK; 132 99 133 if (name.substr(0, 8) == L"special/") 100 // Also ignore some subfolders. 101 if (name.substr(0, 8) == L"special/" || name.substr(0, 7) == L"mixins/") 134 102 return INFO::OK; 135 103 … … 179 147 const CParamNode& CTemplateLoader::GetTemplateFileData(const std::string& templateName) 180 148 { 181 // Load the template if necessary 182 if (!LoadTemplateFile(templateName, 0)) 149 if (std::unordered_map<std::string, CParamNode>::const_iterator it = m_TemplateFileData.find(templateName); it != m_TemplateFileData.end()) 150 return it->second; 151 152 CParamNode ret; 153 if (!LoadTemplateFile(ret, templateName, false, 0)) 183 154 { 184 155 LOGERROR("Failed to load entity template '%s'", templateName.c_str()); 185 156 return NULL_NODE; 186 157 } 187 188 return m_TemplateFileData[templateName]; 158 return m_TemplateFileData.insert_or_assign(templateName, ret).first->second; 189 159 } 190 160 191 void CTemplateLoader::ConstructTemplateActor( const std::string&actorName, CParamNode& out)161 void CTemplateLoader::ConstructTemplateActor( actorName, CParamNode& out) 192 162 { 193 163 // Copy the actor template … … 195 165 196 166 // Initialize the actor's name and make it an Atlas selectable entity. 197 std:: wstring actorNameW = wstring_from_utf8(actorName);198 std:: string name = utf8_from_wstring(CParamNode::EscapeXMLString(actorNameW));199 s td::string xml= "<Entity>"200 "<VisualActor><Actor>" + name + "</Actor><ActorOnly/></VisualActor>"201 202 203 204 205 206 207 208 209 CParamNode::LoadXMLString(out, xml.c_str(), actorNameW.c_str());167 std::(actorName); 168 std::); 169 s = "<Entity>" 170 e + "</Actor><ActorOnly/></VisualActor>" 171 // Arbitrary-sized Footprint definition to make actors' selection outlines show up in Atlas. 172 "<Footprint><Circle radius='2.0'/><Height>1.0</Height></Footprint>" 173 "<Selectable>" 174 "<EditorOnly/>" 175 "<Overlay><Texture><MainTexture>128x128/ellipse.png</MainTexture><MainTextureMask>128x128/ellipse_mask.png</MainTextureMask></Texture></Overlay>" 176 "</Selectable>" 177 "</Entity>"; 178 // We'll assume that actorName is valid XML, otherwise this will fail and report the error anyways. 179 CParamNode::LoadXMLString(out, .c_str(), actorNameW.c_str()); 210 180 } -
ps/trunk/source/ps/TemplateLoader.h
r20519 r25223 1 /* Copyright (C) 20 17Wildfire Games.1 /* Copyright (C) 20 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * … … 20 20 21 21 #include "simulation2/system/ParamNode.h" 22 23 24 22 25 23 26 enum ETemplatesType … … 70 73 * and saves into m_TemplateFileData. Also loads any parents that are not yet 71 74 * loaded. Returns false on error. 72 * @param templateName XML filename to load (not a |-separated string) 75 * @param templateName - XML filename to load (may be a |-separated string) 76 * @param compositing - whether this template is an intermediary layer in a |-separated string. 77 * @param depth - the current recursion depth. 73 78 */ 74 bool LoadTemplateFile( const std::string& templateName, int depth);79 bool LoadTemplateFile(, int depth); 75 80 76 81 /** 77 82 * Constructs a standard static-decorative-object template for the given actor 78 83 */ 79 void ConstructTemplateActor( const std::string&actorName, CParamNode& out);84 void ConstructTemplateActor( actorName, CParamNode& out); 80 85 81 86 /** … … 85 90 * when hotloading broken files) 86 91 */ 87 std:: map<std::string, CParamNode> m_TemplateFileData;92 std::map<std::string, CParamNode> m_TemplateFileData; 88 93 }; 89 94 -
ps/trunk/source/tools/entity/Entity.pm
r22096 r25223 13 13 { 14 14 my ($vfspath, $mod) = @_; 15 my $fn = "$vfsroot/$mod/simulation/templates/$vfspath.xml"; 15 my $fn = "$vfsroot/$mod/simulation/templates/special/filter/$vfspath.xml"; 16 if (not -e $fn) { 17 $fn = "$vfsroot/$mod/simulation/templates/mixins/$vfspath.xml"; 18 } 19 if (not -e $fn) { 20 $fn = "$vfsroot/$mod/simulation/templates/$vfspath.xml"; 21 } 16 22 return $fn; 17 23 } … … 137 143 sub load_inherited 138 144 { 139 my ($vfspath, $mods) = @_; 145 my ($vfspath, $mods, $base) = @_; 146 if ($vfspath =~ /\|/) { 147 my @paths = split(/\|/, $vfspath, 2); 148 $base = load_inherited($paths[1], $mods, $base); 149 $base = load_inherited($paths[0], $mods, $base); 150 return $base 151 } 140 152 my $main_mod = get_main_mod($vfspath, $mods); 141 153 my $layer = load_xml($vfspath, get_file($vfspath, $main_mod)); 142 154 143 155 if ($layer->{Entity}{'@parent'}) { 144 my $parent = load_inherited($layer->{Entity}{'@parent'}{' content'}, $mods );156 my $parent = load_inherited($layer->{Entity}{'@parent'}{' content'}, $mods); 145 157 apply_layer($parent->{Entity}, $layer->{Entity}); 146 158 return $parent; 147 159 } else { 148 return $layer; 160 if (not $base) { 161 return $layer; 162 } 163 else { 164 apply_layer($base->{Entity}, $layer->{Entity}); 165 return $base 166 } 149 167 } 150 168 } -
ps/trunk/source/tools/entity/checkrefs.pl
r25022 r25223 131 131 my $ent = Entity::load_inherited($f, "$mod_list_string"); 132 132 133 push @deps, [ $path, "simulation/templates/" . $ent->{Entity}{'@parent'}{' content'} . ".xml" ] if $ent->{Entity}{'@parent'}; 133 if ($ent->{Entity}{'@parent'}) 134 { 135 my @parents = split(/\|/, $ent->{Entity}{'@parent'}{' content'}); 136 for my $parentPath (@parents) 137 { 138 push @deps, [ $path, "simulation/templates/" . $parentPath . ".xml" ]; 139 } 140 } 134 141 135 142 if ($f !~ /^template_/) … … 639 646 for my $f (sort keys %revdeps) 640 647 { 648 649 650 651 652 641 653 next if exists $files{$f}; 642 654 warn "Missing file '$f' referenced by: " . (join ', ', map "'$_'", map vfs_to_relative_to_mods($_), sort @{$revdeps{$f}}) . "\n";
Note:
See TracChangeset
for help on using the changeset viewer.