Browse Source

Add attribute file compatibility shim

nosoop 1 year ago
parent
commit
e3d6a9572b
1 changed files with 206 additions and 0 deletions
  1. 206 0
      scripting/tf_econ_dynamic_compat.sp

+ 206 - 0
scripting/tf_econ_dynamic_compat.sp

@@ -0,0 +1,206 @@
+/**
+ * [TF2] Econ Dynamic Compatibility Shim
+ * 
+ * Implements compatibility shims to load attribute definitions from files.
+ */
+#pragma semicolon 1
+#include <sourcemod>
+
+#pragma newdecls required
+
+#include <tf_econ_dynamic>
+
+#define PLUGIN_VERSION "1.0.0"
+public Plugin myinfo = {
+	name = "[TF2] Econ Dynamic Compatibility Shim",
+	author = "nosoop",
+	description = "Compatibility shim to install attributes specified by other plugins",
+	version = PLUGIN_VERSION,
+	url = "https://github.com/nosoop/SMExt-TFEconDynamic"
+}
+
+static EconInjectedAttribute s_AttributeContext;
+
+public void OnPluginStart() {
+	s_AttributeContext = new EconInjectedAttribute();
+	
+	CreateAttributeConfigParsers();
+}
+
+public void OnMapStart() {
+	// this loads relatively late, but it should be fine
+	LoadAttributes();
+}
+
+enum HiddenAttributeConfigParseState {
+	HiddenAttributeConfigParseState_Root,
+	
+	HiddenAttributeConfigParseState_AttributeList,
+	HiddenAttributeConfigParseState_AttributeProperties,
+}
+
+static SMCParser s_HiddenDevAttributeParser;
+
+static HiddenAttributeConfigParseState s_ParseState = HiddenAttributeConfigParseState_Root;
+static int s_nParseStateIgnoreNestedSections;
+
+void CreateAttributeConfigParsers() {
+	s_HiddenDevAttributeParser = new SMCParser();
+	
+	
+	s_HiddenDevAttributeParser.OnStart = OnAttributeConfigStartParse;
+	s_HiddenDevAttributeParser.OnEnd = OnAttributeConfigEndParse;
+	
+	s_HiddenDevAttributeParser.OnEnterSection = OnAttributeConfigEnterSection;
+	s_HiddenDevAttributeParser.OnLeaveSection = OnAttributeConfigLeaveSection;
+	
+	s_HiddenDevAttributeParser.OnKeyValue = OnAttributeConfigKeyValue;
+}
+
+void OnAttributeConfigStartParse(SMCParser smc) {
+	s_ParseState = HiddenAttributeConfigParseState_Root;
+	s_nParseStateIgnoreNestedSections = 0;
+}
+
+/**
+ * Push new parse state depending on the current section.
+ */
+SMCResult OnAttributeConfigEnterSection(SMCParser smc, const char[] name, bool opt_quotes) {
+	/**
+	 * If we're ignoring a parent section, increment and don't emit a change in parse state.
+	 */
+	if (s_nParseStateIgnoreNestedSections) {
+		s_nParseStateIgnoreNestedSections++;
+		return SMCParse_Continue;
+	}
+	
+	switch (s_ParseState) {
+		case HiddenAttributeConfigParseState_Root: {
+			if (StrEqual(name, "attributes", .caseSensitive = false)) {
+				s_ParseState = HiddenAttributeConfigParseState_AttributeList;
+			} else {
+				LogError("Entering unexpected section '%s' while in parse state %d", name, s_ParseState);
+				return SMCParse_HaltFail;
+			}
+		}
+		case HiddenAttributeConfigParseState_AttributeList: {
+			s_AttributeContext.Clear();
+			
+			int attrdef;
+			if (StrEqual(name, "auto", .caseSensitive = false)) {
+				// do nothing
+			} else if (StringToIntEx(name, attrdef)) {
+				s_AttributeContext.SetDefIndex(attrdef);
+#if defined DEBUG
+				LogMessage("Setting attribute context to itemdef %d", attrdef);
+#endif
+			} else {
+				LogError("Attempting to declare attribute with invalid defindex '%s'", name);
+				return SMCParse_HaltFail;
+			}
+			s_ParseState = HiddenAttributeConfigParseState_AttributeProperties;
+		}
+		case HiddenAttributeConfigParseState_AttributeProperties: {
+			// ignore nested properties for now
+			LogMessage("Warning: Nested keys are not currently supported");
+			s_nParseStateIgnoreNestedSections++;
+		}
+		default: {
+			LogError("Entering unexpected section '%s' while in parse state %d", name,
+					s_ParseState);
+			return SMCParse_HaltFail;
+		}
+	}
+	return SMCParse_Continue;
+}
+
+/**
+ * Pop parse state and go back to previous one.
+ */
+SMCResult OnAttributeConfigLeaveSection(SMCParser smc) {
+	/**
+	 * If we're leaving an ignored section, decrement and don't emit a change in parse state.
+	 */
+	if (s_nParseStateIgnoreNestedSections) {
+		s_nParseStateIgnoreNestedSections--;
+		return SMCParse_Continue;
+	}
+	
+	switch (s_ParseState) {
+		case HiddenAttributeConfigParseState_AttributeProperties: {
+			s_ParseState = HiddenAttributeConfigParseState_AttributeList;
+			s_AttributeContext.Register();
+		}
+		case HiddenAttributeConfigParseState_AttributeList: {
+			s_ParseState = HiddenAttributeConfigParseState_Root;
+		}
+		case HiddenAttributeConfigParseState_Root: {
+			LogError("Leaving section while in root parse state");
+		}
+		default: {
+			LogError("Leaving section while in parse state %d", s_ParseState);
+		}
+	}
+	return SMCParse_Continue;
+}
+
+SMCResult OnAttributeConfigKeyValue(SMCParser smc, const char[] key, const char[] value,
+		bool key_quotes, bool value_quotes) {
+	switch (s_ParseState) {
+		case HiddenAttributeConfigParseState_AttributeProperties: {
+			s_AttributeContext.SetCustom(key, value);
+#if defined DEBUG
+			LogMessage("Adding attribute context key / value: '%s' = '%s'", key, value);
+#endif
+		}
+		default: {
+			LogError("Unexpected key / value pair while in parse state %d", s_ParseState);
+		}
+	}
+	return SMCParse_Continue;
+}
+
+void OnAttributeConfigEndParse(SMCParser smc, bool halted, bool failed) {
+	if (halted || failed) {
+		return;
+	}
+	
+	if (s_ParseState != HiddenAttributeConfigParseState_Root) {
+		LogError("Parse state not at root on end parse");
+	}
+}
+
+void LoadAttributes() {
+	char configDir[PLATFORM_MAX_PATH];
+	BuildPath(Path_SM, configDir, sizeof(configDir), "configs/tf2nativeattribs");
+
+	if (!DirExists(configDir, false)) {
+		return;
+	}
+	
+	DirectoryListing list = OpenDirectory(configDir, false);
+	FileType fileType;
+	char filename[PLATFORM_MAX_PATH];
+
+	while (list.GetNext(filename, sizeof(filename), fileType)) {
+		if (fileType != FileType_File) {
+			continue;
+		}
+		
+		Format(filename, sizeof(filename), "%s/%s", configDir, filename);
+
+		if (strncmp(filename[strlen(filename) - 4], ".txt", 4, false) != 0) {
+			PrintToServer("[TF2 Econ Dynamic] "
+					... "Attributes file %s does not have a txt extension. "
+					... "Attributes will not be loaded",
+					filename);
+			continue;
+		}
+
+		if (s_HiddenDevAttributeParser.ParseFile(filename) != SMCError_Okay) {
+			PrintToServer("[TF2 Econ Dynamic] "
+					... "Failed to load file %s. Attributes will not be loaded",
+					filename);
+		}
+	}
+}