[TUTORIAL] Writing an Extension (AMX Mod X Module)

Adding Modules to help with scripting/coding plugins.
User avatar
Archive-Poster
Posts: 1090
Gender:
United States of America

[TUTORIAL] Writing an Extension (AMX Mod X Module)

Post by Archive-Poster »

It's very importantly to know that an extension is a Dynamic Library (DLL) and not a program (EXE). When compiling a C++ program using GCC, adding -shared parameter will set compiler to compile a DLL file and not an executable one.

Usually, a project for an AMX Mod X module requires a lot of header files, not only the ones provided by the operating system. These headers are placed into a folder, for example. A folder named HLSDK that represents the game headers and another one named METAMOD that represents the METAMOD linkage.

To make sure the headers will be available for the project, add parameters -IHLSDK -IMETAMOD -I. -IAnotherFolderName -IMyHeaders or how many folders you want.

The command line for GCC Linux should look like the one listed below.

Code: Select all

gcc Source.cpp Helper.cpp SomeFolder/SomeSource.cpp -ISomeHeaders -IAnotherHeaders -IHattrick/Headers -shared -o Library.so
If you have some header files around your source files, add parameter -I. to make sure the header files will be included.

If you want to link some libraries to you project, type the library name and its extension beside the source files into the GCC compiling command like listed below. In this example, MySQL.a library will be used.

Code: Select all

gcc Source.cpp Helper.cpp SomeFolder/SomeSource.cpp MySQL.a -ISomeHeaders -IAnotherHeaders -IHattrick/Headers -shared -o Library.so
If you want your library to be attached on different operating systems, like a project compiled on Ubuntu to work on Debian, you will need more flags. For this, you will need to use Makefile file. Place the file named 'Makefile' where the project is (around the source files) and then type in Terminal application the command make. A Makefile should look like the one below.

Code: Select all

# Makefile written by Hattrick (Claudiu HKS)
# Support taken from http://forums.alliedmods.net

PROJECT = furien_mod_amxx_i386.so

INCLUDE = -I. \
    -IHLSDK -IMETAMOD

OBJECTS = amxxmodule.cpp \
    Source.cpp

FLAGS = -DNDEBUG -O2 -funroll-loops -fomit-frame-pointer -pipe \
    -fvisibility=hidden -fvisibility-inlines-hidden -DLINUX \
    -shared -m32 -lm -ldl -DPAWN_CELL_SIZE=32 -DJIT -DASM32 \
    -DHAVE_STDINT_H -fno-strict-aliasing -fno-exceptions \
    -fno-rtti -s -Wno-delete-non-virtual-dtor -static-libgcc \
    -D_snprintf=snprintf -D_strcpy=strcpy -D_strcat=strcat \
    -D_snprintf_s=snprintf -D_strncpy=strncpy -D_strncat=strncat \
    -D_stricmp=strcasecmp -D_strcmp=strcmp -D_strncmp=strncmp \
    -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
    -Dstricmp=strcasecmp
 
# -DJIT // #define JIT
# -DASM32 // #define ASM32
# -DPAWN_CELL_SIZE=32 // #define PAWN_CELL_SIZE 32
# -DHAVE_STDINT_H // #define HAVE_STDINT_H
# -DLINUX // #define LINUX
 
# Information
# -------------------
# If you will get a message like symbol TRUE is not defined, add parameters:
# -DTRUE=1 -DFALSE=0
# If you will get a message like symbol PCHAR is not defined, add parameter:
# -DPCHAR=char* -DPFLOAT=float* -DFLOAT=float -DPSHORT=short*
# Et cetera.
 
# Now build the project.
default:
    gcc $(OBJECTS) $(FLAGS) $(INCLUDE) -o $(PROJECT) 
For Windows, if you want your project to be able to run on other operating systems, like a project compiled on Windows 8.1 to be able to work on Windows XP, you will have to edit some properties. Your VCXPROJ file should be looking like the one below.

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{C5A8397C-7CCC-4B4E-A005-36EE6E6B872F}</ProjectGuid>
    <RootNamespace>FurienMod</RootNamespace>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v120_xp</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>MultiByte</CharacterSet>
    <UseOfMfc>false</UseOfMfc>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <TargetName>furien_mod_amxx</TargetName>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Midl>
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Win32</TargetEnvironment>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </Midl>
    <ClCompile>
      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
      <WarningLevel>EnableAllWarnings</WarningLevel>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <BrowseInformation>true</BrowseInformation>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <StringPooling>true</StringPooling>
      <RuntimeTypeInfo>false</RuntimeTypeInfo>
      <SDLCheck>true</SDLCheck>
      <AdditionalIncludeDirectories>HLSDK;METAMOD</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_WINDOWS;NDEBUG;_USRDLL;WIN;WIN32;__WIN;__WIN32;_WIN_;_WIN;__WIN32__;_WIN32;_WIN32_;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x041d</Culture>
    </ResourceCompile>
    <Link>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableUAC>false</EnableUAC>
      <SubSystem>Windows</SubSystem>
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="amxxmodule.cpp" />
    <ClCompile Include="Source.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="amxxmodule.h" />
    <ClInclude Include="Header.h" />
    <ClInclude Include="moduleconfig.h" />
    <ClInclude Include="resource.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Furien Mod.rc" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>
For better support, open an already made project and edit it as you like, and then compile it. For example, Fun module by AMX Mod X Development Team. Almost each VCXPROJ setting is important, let's say that <RuntimeLibrary>MultiThreaded</RuntimeLibrary> will make project to link all needed dependencies inside it so these dependencies won't be needed separately on the newer machine where the extension will run.

Where should the compiling command be written? If you use Linux, in Terminal or Root Terminal applications, otherwise in Command Prompt. To install the GCC compiler, type into Terminal for Linux sudo apt-get install g++ and for Windows, install MinGW or Code::Blocks.

If you want to compile on Windows using Visual Studio, you need to edit the project properties by pressing the right button of the mouse on the project name and then selecting Properties.

You will have to edit the additional include directories and the additional dependencies to link new libraries, if any.

Into Additional Include Directories field add for example: .;..;HLSDK;METAMOD.

If you want to link some libraries like Regular Expressions (REGEX.LIB) or MySQL Client (MYSQLCLIENT.LIB) add into Additional Dependencies field, at Linking category, the next ones: REGEX\REGEX.LIB;MYSQL\Libraries\MYSQLCLIENT.L IB.

Do not consider compiler warnings. Only errors will block the process. How to solve errors? Read the messages from the compiler and then edit your source or header files until everything will be fine.

Before starting to compile, type in the Command Prompt or in Terminal cd C:\Projects\Project or cd '/home/Claudiu/Scripting' to be into the folder where the source files are.

The main entry for a DLL is BOOL APIENTRY /* APIENTRY, WINAPI or __stdcall */ DllMain(HINSTANCE hInst, DWORD nReason, LPVOID dummyParam) and for an EXE is void /* void or int */ main(SIZE_T argsCnt, CHAR ** argsList).

Code: Select all

-shared          // Dynamic library
-o                 // Output
-I                 // Includes directory
gcc              // Compiler
-D                // Defines
-static-libgcc   // Links current dependencies to project
The AMX Mod X source files:
Attachments
Makefile + VCXPROJ.zip
(2.06 KiB) Downloaded 4 times
HLSDK + METAMOD Headers.zip
(225.59 KiB) Downloaded 4 times

Who is online

Users browsing this forum: No registered users and 0 guests