pred@2224: /** pred@2224: * vim: set ts=4 : pred@2224: * ============================================================================= pred@2224: * SourceMod Sample Extension pred@2224: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. pred@2224: * ============================================================================= pred@2224: * pred@2224: * This program is free software; you can redistribute it and/or modify it under pred@2224: * the terms of the GNU General Public License, version 3.0, as published by the pred@2224: * Free Software Foundation. pred@2224: * pred@2224: * This program is distributed in the hope that it will be useful, but WITHOUT pred@2224: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS pred@2224: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more pred@2224: * details. pred@2224: * pred@2224: * You should have received a copy of the GNU General Public License along with pred@2224: * this program. If not, see . pred@2224: * pred@2224: * As a special exception, AlliedModders LLC gives you permission to link the pred@2224: * code of this program (as well as its derivative works) to "Half-Life 2," the pred@2224: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software pred@2224: * by the Valve Corporation. You must obey the GNU General Public License in pred@2224: * all respects for all other code used. Additionally, AlliedModders LLC grants pred@2224: * this exception to all derivative works. AlliedModders LLC defines further pred@2224: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), pred@2224: * or . pred@2224: * pred@2224: * Version: $Id$ pred@2224: */ pred@2224: pred@2224: #include "extension.h" pred@2224: pred@2224: /** pred@2224: * @file extension.cpp pred@2224: * @brief Implement extension code here. pred@2224: */ pred@2224: pred@2224: Structs g_Structs; /**< Global singleton for extension's main interface */ pred@2224: pred@2224: SMEXT_LINK(&g_Structs); pred@2224: pred@2224: HandleType_t g_StructHandle = 0; pred@2224: StructHandler g_StructHandler; pred@2224: pred@2224: IGameConfig *conf; pred@2224: pred@2224: size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) pred@2224: { pred@2224: va_list ap; pred@2224: va_start(ap, fmt); pred@2224: size_t len = vsnprintf(buffer, maxlength, fmt, ap); pred@2224: va_end(ap); pred@2224: pred@2224: if (len >= maxlength) pred@2224: { pred@2224: buffer[maxlength - 1] = '\0'; pred@2224: return (maxlength - 1); pred@2224: } pred@2224: else pred@2224: { pred@2224: return len; pred@2224: } pred@2224: } pred@2224: pred@2224: void Structs::SDK_OnAllLoaded() pred@2224: { pred@2224: g_StructHandle = handlesys->CreateType("Struct", pred@2224: &g_StructHandler, pred@2224: 0, pred@2224: NULL, pred@2224: NULL, pred@2224: myself->GetIdentity(), pred@2224: NULL); pred@2224: pred@2224: gameconfs->AddUserConfigHook("Structs", this); pred@2224: pred@2224: sharesys->AddNatives(myself, MyNatives); pred@2224: pred@2224: pred@2224: char error[100]; dvander@2386: if (!gameconfs->LoadGameConfigFile("structs.gamedata", &conf, error, sizeof(error))) pred@2224: { pred@2224: g_pSM->LogError(myself, "Parsing Failed!"); pred@2224: } pred@2224: } pred@2224: pred@2224: void Structs::SDK_OnUnload() pred@2224: { pred@2224: handlesys->RemoveType(g_StructHandle, myself->GetIdentity()); dvander@2385: gameconfs->CloseGameConfigFile(conf); pred@2224: gameconfs->RemoveUserConfigHook("Structs", this); pred@2224: } pred@2224: pred@2224: bool Structs::SDK_OnLoad( char *error, size_t maxlength, bool late ) pred@2224: { pred@2224: sharesys->AddInterface(myself, &g_StructManager); pred@2224: pred@2224: m_typeLookup.insert("int", Member_Int32); pred@2224: m_typeLookup.insert("int*", Member_Int32Pointer); pred@2224: m_typeLookup.insert("float", Member_Float); pred@2224: m_typeLookup.insert("float*", Member_FloatPointer); pred@2224: m_typeLookup.insert("char", Member_Char); pred@2224: m_typeLookup.insert("char*", Member_CharPointer); pred@2224: m_typeLookup.insert("Vector", Member_Vector); pred@2224: m_typeLookup.insert("Vector*", Member_VectorPointer); pred@2224: m_typeLookup.insert("ent", Member_EHandle); pred@2224: m_typeLookup.insert("ent*", Member_EHandlePointer); pred@2224: pred@2224: return true; pred@2224: } pred@2224: pred@2224: void Structs::ReadSMC_ParseStart() pred@2224: { pred@2224: m_bInStruct = false; pred@2224: m_currentStruct = NULL; pred@2224: m_bInMember = false; pred@2224: m_currentMember = NULL; pred@2224: } pred@2224: pred@2224: SourceMod::SMCResult Structs::ReadSMC_NewSection( const SMCStates *states, const char *name ) pred@2224: { pred@2224: if (!m_bInStruct) pred@2224: { pred@2224: m_currentStruct = new StructInfo(); pred@2224: UTIL_Format(m_currentStruct->name, sizeof(m_currentStruct->name), "%s", name); pred@2224: m_bInStruct = true; pred@2224: pred@2224: return SMCResult_Continue; pred@2224: } pred@2224: pred@2224: if (!m_bInMember) pred@2224: { pred@2224: m_bInMember = true; pred@2224: m_currentMember = new MemberInfo(); pred@2224: UTIL_Format(m_currentMember->name, sizeof(m_currentMember->name), "%s", name); pred@2224: pred@2224: return SMCResult_Continue; pred@2224: } pred@2224: pred@2224: g_pSM->LogMessage(myself, "Cannot nest within a member: line: %i col: %i", states->line, states->col); pred@2224: pred@2224: return SMCResult_HaltFail; pred@2224: } pred@2224: pred@2224: SourceMod::SMCResult Structs::ReadSMC_KeyValue( const SMCStates *states, const char *key, const char *value ) pred@2224: { pred@2224: if (!m_bInStruct) pred@2224: { pred@2224: //hrm.. pred@2224: g_pSM->LogMessage(myself, "Unknown value %s: line: %i col: %i", key, states->line, states->col); pred@2224: return SMCResult_HaltFail; pred@2224: } pred@2224: pred@2224: if (m_bInMember) pred@2224: { pred@2224: if (strcmp(key, "type") == 0) pred@2224: { pred@2224: MemberType *pType = m_typeLookup.retrieve(value); pred@2224: pred@2224: if (pType == NULL) pred@2224: { pred@2224: //invalid type pred@2224: g_pSM->LogMessage(myself, "Invalid Type: line: %i col: %i", states->line, states->col); pred@2224: return SMCResult_HaltFail; pred@2224: } pred@2224: pred@2224: /* Note all 'int' types are assumed to be 32bit for the moment */ pred@2224: m_currentMember->type = *pType; pred@2224: } pred@2224: else if (strcmp(key, "size") == 0) pred@2224: { pred@2224: m_currentMember->size = atoi(value); pred@2224: } pred@2224: #if defined WIN32 pred@2224: else if (strcmp(key, "windows") == 0) pred@2224: #else pred@2224: else if (strcmp(key, "linux") == 0) pred@2224: #endif pred@2224: { pred@2224: m_currentMember->offset = atoi(value); pred@2224: } pred@2224: } pred@2224: else pred@2224: { pred@2224: if (strcmp(key, "size") == 0) pred@2224: { pred@2224: m_currentStruct->size = atoi(value); pred@2224: } pred@2224: } pred@2224: pred@2224: return SMCResult_Continue; pred@2224: } pred@2224: pred@2224: SourceMod::SMCResult Structs::ReadSMC_LeavingSection( const SMCStates *states ) pred@2224: { pred@2224: if (m_bInMember) pred@2224: { pred@2224: /** Check for missing or invalid parameters */ pred@2224: if (m_currentMember->type == Member_Unknown || m_currentMember->offset == -1) pred@2224: { pred@2224: g_pSM->LogMessage(myself, "Missing offset or type: line: %i col: %i", states->line, states->col); pred@2224: return SMCResult_HaltFail; pred@2224: } pred@2224: pred@2224: if (m_currentMember->size == -1) pred@2224: { pred@2224: switch (m_currentMember->type) pred@2224: { pred@2224: case Member_Float: pred@2224: case Member_FloatPointer: pred@2224: case Member_Vector: pred@2224: case Member_VectorPointer: pred@2224: case Member_EHandle: pred@2224: case Member_EHandlePointer: pred@2224: { pred@2224: break; pred@2224: } pred@2224: pred@2224: default: pred@2224: { pred@2224: g_pSM->LogMessage(myself, "Missing size: line: %i col: %i", states->line, states->col); pred@2224: return SMCResult_HaltFail; pred@2224: } pred@2224: } pred@2224: } pred@2224: pred@2224: /* Work out the int size */ pred@2224: if (m_currentMember->type == Member_Int32) pred@2224: { pred@2224: if (m_currentMember->size == 1) pred@2224: { pred@2224: m_currentMember->type = Member_Int8; pred@2224: } pred@2224: else if (m_currentMember->size == 2) pred@2224: { pred@2224: m_currentMember->type = Member_Int16; pred@2224: } pred@2224: else if (m_currentMember->size == 4) pred@2224: { pred@2224: m_currentMember->type = Member_Int32; pred@2224: } pred@2224: else pred@2224: { pred@2224: g_pSM->LogMessage(myself, "Invalid int size %i: line: %i col: %i", m_currentMember->size, states->line, states->col); pred@2224: return SMCResult_HaltFail; pred@2224: } pred@2224: pred@2224: } pred@2224: else if (m_currentMember->type == Member_Int32) pred@2224: { pred@2224: if (m_currentMember->size == 1) pred@2224: { pred@2224: m_currentMember->type = Member_Int8Pointer; pred@2224: } pred@2224: else if (m_currentMember->size == 2) pred@2224: { pred@2224: m_currentMember->type = Member_Int16Pointer; pred@2224: } pred@2224: else if (m_currentMember->size == 4) pred@2224: { pred@2224: m_currentMember->type = Member_Int32Pointer; pred@2224: } pred@2224: else pred@2224: { pred@2224: g_pSM->LogMessage(myself, "Invalid int size %i: line: %i col: %i", m_currentMember->size, states->line, states->col); pred@2224: return SMCResult_HaltFail; pred@2224: } pred@2224: } pred@2224: pred@2224: m_currentStruct->AddMember(m_currentMember->name, m_currentMember); pred@2224: pred@2224: m_bInMember = false; pred@2224: m_currentMember = NULL; pred@2224: pred@2224: return SMCResult_Continue; pred@2224: } pred@2224: pred@2224: g_StructManager.AddStruct(m_currentStruct->name, m_currentStruct); pred@2224: pred@2224: m_bInStruct = false; pred@2224: m_currentStruct = NULL; pred@2224: pred@2224: return SMCResult_Continue; pred@2224: }