2016-11-01 03:53:07 +07:00
|
|
|
/*
|
|
|
|
|
* sfall
|
|
|
|
|
* Copyright (C) 2008, 2009, 2010, 2012 The sfall team
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2016-11-02 04:10:50 +07:00
|
|
|
#include <sstream>
|
2016-11-01 03:53:07 +07:00
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
#include "ScriptExtender.h"
|
|
|
|
|
|
2016-11-02 04:10:50 +07:00
|
|
|
// Metarule is a universal opcode(s) for all kinds of new sfall scripting functions.
|
|
|
|
|
// Prefix all function handlers with sf_ and add them to sfall_metarule_table.
|
|
|
|
|
// DO NOT add arguments and/or return values to function handlers!
|
|
|
|
|
// Use functions GetOpArgXXX(), IsOpArgXXX() inside handler function to read arguments, but argument 0 is always function name.
|
|
|
|
|
// Use SetOpReturn() to set return value.
|
|
|
|
|
// If you want to call user-defined procedures in your handler, use RunScriptProc().
|
2016-11-01 03:53:07 +07:00
|
|
|
|
2016-11-02 04:10:50 +07:00
|
|
|
typedef std::tr1::unordered_map<const char*, void(*)()> MetaruleTableType;
|
|
|
|
|
|
|
|
|
|
static MetaruleTableType metaruleTable;
|
|
|
|
|
|
|
|
|
|
static std::string sf_test_stringBuf;
|
|
|
|
|
|
|
|
|
|
// Example handler. Feel free to add handlers in other files.
|
2016-11-01 03:53:07 +07:00
|
|
|
static void sf_test() {
|
2016-11-02 04:10:50 +07:00
|
|
|
std::ostringstream sstream;
|
|
|
|
|
sstream << "sfall_func(\"test\"";
|
|
|
|
|
for (DWORD i = 1; i < opArgCount; i++) {
|
|
|
|
|
sstream << ", ";
|
|
|
|
|
switch (opArgTypes[i]) {
|
|
|
|
|
case DATATYPE_INT:
|
|
|
|
|
sstream << GetOpArgInt(i);
|
|
|
|
|
break;
|
|
|
|
|
case DATATYPE_FLOAT:
|
|
|
|
|
sstream << GetOpArgFloat(i);
|
|
|
|
|
break;
|
|
|
|
|
case DATATYPE_STR:
|
|
|
|
|
sstream << '"' << GetOpArgStr(i) << '"';
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
sstream << "???";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sstream << ");";
|
|
|
|
|
|
|
|
|
|
sf_test_stringBuf = sstream.str();
|
|
|
|
|
SetOpReturn(sf_test_stringBuf.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// returns current contents of metarule table
|
|
|
|
|
static void sf_get_metarule_table() {
|
|
|
|
|
DWORD arr = TempArray(metaruleTable.size(), 0);
|
|
|
|
|
int i = 0;
|
|
|
|
|
for (MetaruleTableType::iterator it = metaruleTable.begin(); it != metaruleTable.end(); it++) {
|
|
|
|
|
arrays[arr].val[i].set(it->first);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
SetOpReturn(arr, DATATYPE_INT);
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void InitMetaruleTable() {
|
2016-11-02 04:10:50 +07:00
|
|
|
metaruleTable["test"] = sf_test;
|
|
|
|
|
metaruleTable["get_metarule_table"] = sf_get_metarule_table;
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
|
|
|
|
|
2016-11-02 04:10:50 +07:00
|
|
|
static void _stdcall op_sfall_metarule_handler() {
|
2016-11-01 03:53:07 +07:00
|
|
|
if (IsOpArgStr(0)) {
|
2016-11-02 04:10:50 +07:00
|
|
|
const char* name = GetOpArgStr(0);
|
|
|
|
|
MetaruleTableType::iterator lookup = metaruleTable.find(name);
|
|
|
|
|
if (lookup != metaruleTable.end()) {
|
2016-11-01 03:53:07 +07:00
|
|
|
lookup->second();
|
|
|
|
|
} else {
|
2016-11-02 04:10:50 +07:00
|
|
|
dlog_f("sfall_metaruleX(name, ...) - name '%s' is unknown.", DL_INIT, name);
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
|
|
|
|
} else {
|
2016-11-02 04:10:50 +07:00
|
|
|
dlog("sfall_metaruleX(name, ...) - name must be string.", DL_INIT);
|
|
|
|
|
}
|
|
|
|
|
// Force return value, because metarule opcode is an expression.
|
|
|
|
|
if (opRetType == DATATYPE_NONE) {
|
|
|
|
|
SetOpReturn(0, DATATYPE_INT);
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-02 04:10:50 +07:00
|
|
|
// TODO: replace _WRAP_OPCODE with C++ equivalent
|
|
|
|
|
// TODO: handle string arguments
|
|
|
|
|
|
|
|
|
|
#define metaruleOpcode(numArg, numArgPlusOne) \
|
|
|
|
|
static void __declspec(naked) op_sfall_metarule##numArg() {\
|
|
|
|
|
_WRAP_OPCODE(numArgPlusOne, op_sfall_metarule_handler)\
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
metaruleOpcode(0, 1)
|
|
|
|
|
metaruleOpcode(1, 2)
|
|
|
|
|
metaruleOpcode(2, 3)
|
|
|
|
|
metaruleOpcode(3, 4)
|
|
|
|
|
metaruleOpcode(4, 5)
|
|
|
|
|
metaruleOpcode(5, 6)
|
|
|
|
|
metaruleOpcode(6, 7)
|
|
|
|
|
|
|
|
|
|
#undef metaruleOpcode
|