소스 검색

Avoid overwriting attributes we don't own

nosoop 3 년 전
부모
커밋
c13817c323
1개의 변경된 파일20개의 추가작업 그리고 4개의 파일을 삭제
  1. 20 4
      mmsplugin.cpp

+ 20 - 4
mmsplugin.cpp

@@ -124,13 +124,26 @@ bool DynSchema::Unload(char *error, size_t maxlen) {
  * replaces the appropriate entry in the schema.
  */
 bool InsertOrReplaceAttribute(KeyValues *pAttribKV) {
+	/**
+	 * TODO implement special handling when "auto" is provided; use an autoincrementing value
+	 * that checks for a free slot in the attribute mapping, then internally map the attribute
+	 * name to that value for persistence and so we don't add that attribute multiple times
+	 */
 	int attrdef = atoi(pAttribKV->GetName());
-	
 	if (attrdef <= 0) {
 		return false;
 	}
 	
-	// TODO only replace injected attribute if it exists
+	// only replace existing injected attributes; fail on schema attributes
+	auto existingIndex = g_SchemaAttributes->Find(attrdef);
+	if (existingIndex != g_SchemaAttributes->InvalidIndex()) {
+		auto &existingAttr = g_SchemaAttributes->Element(existingIndex);
+		if (!existingAttr.m_KeyValues->GetBool("injected")) {
+			META_CONPRINTF("WARN: Not overriding native attribute '%s'\n",
+					existingAttr.m_pszName);
+			return false;
+		}
+	}
 	
 	// embed additional custom data into attribute KV; econdata and the like can deal with this
 	// one could also add this data into the file itself, but this leaves less room for error
@@ -155,6 +168,7 @@ bool DynSchema::Hook_LevelInitPost(const char *pMapName, char const *pMapEntitie
 			game_path, "addons/dynattrs/items_dynamic.txt");
 	
 	// always initialize attributes -- it's better than losing attributes on schema reinit
+	// coughhiddendevattributescough
 	
 	// collect raw attribute keyvalue entries scattered across files
 	KeyValues::AutoDelete rawAttributes("attributes");
@@ -162,7 +176,6 @@ bool DynSchema::Hook_LevelInitPost(const char *pMapName, char const *pMapEntitie
 	// read our own dynamic schema file -- this one supports other sections
 	KeyValues::AutoDelete pKVMainConfig("DynamicSchema");
 	if (pKVMainConfig->LoadFromFile(filesystem, buffer)) {
-		// TODO check for devattribs folder and import KVs from there, then do a final pass
 		KeyValues *pKVAttributes = pKVMainConfig->FindKey( "attributes" );
 		if (pKVAttributes) {
 			rawAttributes->RecursiveMergeKeyValues(pKVAttributes);
@@ -193,6 +206,9 @@ bool DynSchema::Hook_LevelInitPost(const char *pMapName, char const *pMapEntitie
 	}
 	filesystem->FindClose(findHandle);
 	
+	// perhaps add some other validations before we actually process our attributes?
+	// TODO ensure the name doesn't clash with existing / newly injected attributes
+	
 	// finally process our attributes
 	FOR_EACH_TRUE_SUBKEY(rawAttributes, kv) {
 		InsertOrReplaceAttribute(kv);
@@ -220,7 +236,7 @@ const char *DynSchema::GetLicense() {
 }
 
 const char *DynSchema::GetVersion() {
-	return "1.2.0";
+	return "1.2.1";
 }
 
 const char *DynSchema::GetDate() {