luaui.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 2,574 行 · 第 1/5 页

CPP
2,574
字号
#include "StdAfx.h"
// LuaUI.cpp: implementation of the CLuaUI class.
//
//////////////////////////////////////////////////////////////////////

#include "LuaUI.h"
#include <set>
#include <cctype>
#include <SDL_keysym.h>
#include <SDL_mouse.h>
#include <SDL_timer.h>
using namespace std;

#include "LuaInclude.h"

#include "Lua/LuaCallInHandler.h"
#include "Lua/LuaUtils.h"
#include "Lua/LuaConstGL.h"
#include "Lua/LuaConstCMD.h"
#include "Lua/LuaConstCMDTYPE.h"
#include "Lua/LuaConstGame.h"
#include "Lua/LuaSyncedRead.h"
#include "Lua/LuaUnsyncedCall.h"
#include "Lua/LuaUnsyncedCtrl.h"
#include "Lua/LuaUnsyncedRead.h"
#include "Lua/LuaFeatureDefs.h"
#include "Lua/LuaUnitDefs.h"
#include "Lua/LuaWeaponDefs.h"
#include "Lua/LuaScream.h"
#include "Lua/LuaOpenGL.h"
#include "Lua/LuaVFS.h"
#include "ExternalAI/GlobalAIHandler.h"
#include "ExternalAI/Group.h"
#include "ExternalAI/GroupHandler.h"
#include "Sim/Units/CommandAI/Command.h"
#include "Game/Camera.h"
#include "Game/Camera/CameraController.h"
#include "Game/Game.h"
#include "Game/GameHelper.h"
#include "Game/PlayerRoster.h"
#include "Game/SelectedUnits.h"
#include "Game/Team.h"
#include "Game/UI/CommandColors.h"
#include "Game/UI/CursorIcons.h"
#include "Game/UI/GuiHandler.h"
#include "Game/UI/InfoConsole.h"
#include "Game/UI/KeyCodes.h"
#include "Game/UI/KeySet.h"
#include "Game/UI/KeyBindings.h"
#include "Game/UI/MiniMap.h"
#include "Game/UI/MouseHandler.h"
#include "Map/ReadMap.h"
#include "Map/BaseGroundDrawer.h"
#include "Rendering/InMapDraw.h"
#include "Rendering/FontTexture.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Units/UnitDefHandler.h"
#include "System/LogOutput.h"
#include "System/NetProtocol.h"
#include "System/FileSystem/FileHandler.h"
#include "System/FileSystem/VFSHandler.h"
#include "System/Platform/ConfigHandler.h"
#include "System/Platform/FileSystem.h"


#if (LUA_VERSION_NUM < 500)
#  define LUA_OPEN_LIB(L, lib) lib(L)
#else
#  define LUA_OPEN_LIB(L, lib) \
     lua_pushcfunction((L), lib); \
     lua_pcall((L), 0, 0, 0);
#endif


extern Uint8 *keys;
extern GLfloat LightDiffuseLand[];
extern GLfloat LightAmbientLand[];


CLuaUI* luaUI = NULL;


const int CMD_INDEX_OFFSET = 1; // starting index for command descriptions


/******************************************************************************/
/******************************************************************************/


void CLuaUI::LoadHandler()
{
	if (luaUI) {
		return;
	}

	SAFE_NEW CLuaUI();

	if (luaUI->L == NULL) {
		delete luaUI;
	}
}


void CLuaUI::FreeHandler()
{
	delete luaUI;
}


/******************************************************************************/

CLuaUI::CLuaUI()
: CLuaHandle("LuaUI", LUA_HANDLE_ORDER_UI, true, NULL)
{
	luaUI = this;

	if (L == NULL) {
		return;
	}

	UpdateTeams();

	haveShockFront = false;
	shockFrontMinArea  = 0.0f;
	shockFrontMinPower = 0.0f;
	shockFrontDistAdj  = 100.0f;

	haveWorldTooltip = false;
	haveMapDrawCmd = false;

	const string code = LoadFile("gui.lua");
	if (code.empty()) {
		KillLua();
		return;
	}

	// load the standard libraries
	LUA_OPEN_LIB(L, luaopen_base);
	LUA_OPEN_LIB(L, luaopen_io);
	LUA_OPEN_LIB(L, luaopen_os);
	LUA_OPEN_LIB(L, luaopen_math);
	LUA_OPEN_LIB(L, luaopen_table);
	LUA_OPEN_LIB(L, luaopen_string);
	LUA_OPEN_LIB(L, luaopen_package);
	LUA_OPEN_LIB(L, luaopen_debug);

	// remove a few dangerous calls
	lua_getglobal(L, "io");
	lua_pushstring(L, "popen"); lua_pushnil(L); lua_rawset(L, -3);
	lua_pop(L, 1);
	lua_getglobal(L, "os");
	lua_pushstring(L, "exit");    lua_pushnil(L); lua_rawset(L, -3);
	lua_pushstring(L, "execute"); lua_pushnil(L); lua_rawset(L, -3);
	lua_pop(L, 1);

	lua_pushvalue(L, LUA_GLOBALSINDEX);

	AddBasicCalls(); // into Global

	lua_pushstring(L, "Script");
	lua_rawget(L, -2);
	LuaPushNamedCFunc(L, "UpdateCallIn", CallOutUnsyncedUpdateCallIn);
	lua_pop(L, 1);

	// load the spring libraries
	if (!LoadCFunctions(L)                                                 ||
	    !AddEntriesToTable(L, "VFS",         LuaVFS::PushUnsynced)         ||
	    !AddEntriesToTable(L, "UnitDefs",    LuaUnitDefs::PushEntries)     ||
	    !AddEntriesToTable(L, "WeaponDefs",  LuaWeaponDefs::PushEntries)   ||
	    !AddEntriesToTable(L, "FeatureDefs", LuaFeatureDefs::PushEntries)  ||
	    !AddEntriesToTable(L, "Script",      LuaUnsyncedCall::PushEntries) ||
	    !AddEntriesToTable(L, "Script",      LuaScream::PushEntries)       ||
	    !AddEntriesToTable(L, "Spring",      LuaSyncedRead::PushEntries)   ||
	    !AddEntriesToTable(L, "Spring",      LuaUnsyncedCtrl::PushEntries) ||
	    !AddEntriesToTable(L, "Spring",      LuaUnsyncedRead::PushEntries) ||
	    !AddEntriesToTable(L, "gl",          LuaOpenGL::PushEntries)       ||
	    !AddEntriesToTable(L, "GL",          LuaConstGL::PushEntries)      ||
	    !AddEntriesToTable(L, "Game",        LuaConstGame::PushEntries)    ||
	    !AddEntriesToTable(L, "CMD",         LuaConstCMD::PushEntries)     ||
	    !AddEntriesToTable(L, "CMDTYPE",     LuaConstCMDTYPE::PushEntries)) {
		KillLua();
		return;
	}

	lua_settop(L, 0);

	if (!LoadCode(code, "gui.lua")) {
		KillLua();
		return;
	}

	// register for call-ins
	luaCallIns.AddHandle(this);

	// update extra call-ins
	UnsyncedUpdateCallIn("WorldTooltip");
	UnsyncedUpdateCallIn("MapDrawCmd");

	lua_settop(L, 0);
}


CLuaUI::~CLuaUI()
{
	if (L != NULL) {
		Shutdown();
		KillLua();
	}
	luaUI = NULL;
}


string CLuaUI::LoadFile(const string& filename) const
{
	const char* accessMode = SPRING_VFS_RAW;
	CFileHandler lockFile("gamedata/LockLuaUI.txt", SPRING_VFS_MOD);
	if (lockFile.FileExists()) {
		if (!CLuaHandle::GetDevMode()) {
			logOutput.Print("This mod has locked LuaUI access");
			accessMode = SPRING_VFS_MOD;
		} else {
			logOutput.Print("Bypassing this mod's LuaUI access lock");
			accessMode = SPRING_VFS_RAW SPRING_VFS_MOD;
		}
	}

	CFileHandler f(filename, accessMode);

	string code;
	if (!f.LoadStringData(code)) {
		code.clear();
	}
	return code;
}


bool CLuaUI::HasCallIn(const string& name)
{
	if (L == NULL) {
		return false;
	}

	// never allow these calls
	if (name == "Explosion") {
		return false;
	}

	lua_getglobal(L, name.c_str());
	if (!lua_isfunction(L, -1)) {
		lua_pop(L, 1);
		return false;
	}
	lua_pop(L, 1);
	return true;
}


bool CLuaUI::UnsyncedUpdateCallIn(const string& name)
{
	// never allow this call-in
	if (name == "Explosion") {
		return false;
	}

	if (name == "WorldTooltip") {
		haveWorldTooltip = HasCallIn(name);
		return true;
	}

	if (name == "MapDrawCmd") {
		haveMapDrawCmd = HasCallIn(name);
		return true;
	}

	if (HasCallIn(name)) {
		luaCallIns.InsertCallIn(this, name);
	} else {
		luaCallIns.RemoveCallIn(this, name);
	}
	return true;
}


void CLuaUI::UpdateTeams()
{
	if (luaUI) {
		luaUI->fullCtrl = gs->godMode;
		luaUI->ctrlTeam = gs->godMode ? AllAccessTeam :
		                  (gu->spectating ? NoAccessTeam : gu->myTeam);
		luaUI->fullRead = gu->spectatingFullView;
		luaUI->readTeam = luaUI->fullRead ? AllAccessTeam : gu->myTeam;
		luaUI->readAllyTeam = luaUI->fullRead ? AllAccessTeam : gu->myAllyTeam;
		luaUI->selectTeam = gu->spectatingFullSelect ? AllAccessTeam : gu->myTeam;
	}
}


/******************************************************************************/
/******************************************************************************/

bool CLuaUI::LoadCFunctions(lua_State* L)
{
	lua_newtable(L);

#define REGISTER_LUA_CFUNC(x) \
	lua_pushstring(L, #x);      \
	lua_pushcfunction(L, x);    \
	lua_rawset(L, -3)

	REGISTER_LUA_CFUNC(SendCommands);
	REGISTER_LUA_CFUNC(GiveOrder);
	REGISTER_LUA_CFUNC(GiveOrderToUnit);
	REGISTER_LUA_CFUNC(GiveOrderToUnitMap);
	REGISTER_LUA_CFUNC(GiveOrderToUnitArray);
	REGISTER_LUA_CFUNC(GiveOrderArrayToUnitMap);
	REGISTER_LUA_CFUNC(GiveOrderArrayToUnitArray);

	REGISTER_LUA_CFUNC(SendLuaUIMsg);
	REGISTER_LUA_CFUNC(SendLuaCobMsg);
	REGISTER_LUA_CFUNC(SendLuaGaiaMsg);
	REGISTER_LUA_CFUNC(SendLuaRulesMsg);

	REGISTER_LUA_CFUNC(GetFPS);

	REGISTER_LUA_CFUNC(SetActiveCommand);
	REGISTER_LUA_CFUNC(GetActiveCommand);
	REGISTER_LUA_CFUNC(GetDefaultCommand);
	REGISTER_LUA_CFUNC(GetActiveCmdDescs);
	REGISTER_LUA_CFUNC(GetActiveCmdDesc);
	REGISTER_LUA_CFUNC(GetCmdDescIndex);

	REGISTER_LUA_CFUNC(GetBuildFacing);
	REGISTER_LUA_CFUNC(GetBuildSpacing);

	REGISTER_LUA_CFUNC(GetGatherMode);

	REGISTER_LUA_CFUNC(GetActivePage);
	REGISTER_LUA_CFUNC(ForceLayoutUpdate);

	REGISTER_LUA_CFUNC(GetMouseState);
	REGISTER_LUA_CFUNC(GetMouseMiniMapState);
	REGISTER_LUA_CFUNC(GetMouseStartPosition);
	REGISTER_LUA_CFUNC(GetMouseCursor);
	REGISTER_LUA_CFUNC(SetMouseCursor);
	REGISTER_LUA_CFUNC(WarpMouse);

	REGISTER_LUA_CFUNC(SetCameraOffset);

	REGISTER_LUA_CFUNC(SetShockFrontFactors);

	REGISTER_LUA_CFUNC(SetLosViewColors);

	REGISTER_LUA_CFUNC(GetKeyState);
	REGISTER_LUA_CFUNC(GetModKeyState);
	REGISTER_LUA_CFUNC(GetPressedKeys);
	REGISTER_LUA_CFUNC(GetInvertQueueKey);

	REGISTER_LUA_CFUNC(GetKeyCode);
	REGISTER_LUA_CFUNC(GetKeySymbol);
	REGISTER_LUA_CFUNC(GetKeyBindings);
	REGISTER_LUA_CFUNC(GetActionHotKeys);

	REGISTER_LUA_CFUNC(GetConsoleBuffer);
	REGISTER_LUA_CFUNC(GetCurrentTooltip);

	REGISTER_LUA_CFUNC(GetConfigInt);
	REGISTER_LUA_CFUNC(SetConfigInt);
	REGISTER_LUA_CFUNC(GetConfigString);
	REGISTER_LUA_CFUNC(SetConfigString);

	REGISTER_LUA_CFUNC(CreateDir);
	REGISTER_LUA_CFUNC(MakeFont);
	REGISTER_LUA_CFUNC(SetUnitDefIcon);

	REGISTER_LUA_CFUNC(GetMyAllyTeamID);
	REGISTER_LUA_CFUNC(GetMyTeamID);
	REGISTER_LUA_CFUNC(GetMyPlayerID);

	REGISTER_LUA_CFUNC(GetGroupList);
	REGISTER_LUA_CFUNC(GetSelectedGroup);
	REGISTER_LUA_CFUNC(GetGroupAIName);
	REGISTER_LUA_CFUNC(GetGroupAIList);

	REGISTER_LUA_CFUNC(GetUnitGroup);
	REGISTER_LUA_CFUNC(SetUnitGroup);

	REGISTER_LUA_CFUNC(GetGroupUnits);
	REGISTER_LUA_CFUNC(GetGroupUnitsSorted);
	REGISTER_LUA_CFUNC(GetGroupUnitsCounts);
	REGISTER_LUA_CFUNC(GetGroupUnitsCount);

	REGISTER_LUA_CFUNC(SetShareLevel);
	REGISTER_LUA_CFUNC(ShareResources);

	REGISTER_LUA_CFUNC(MarkerAddPoint);
	REGISTER_LUA_CFUNC(MarkerAddLine);
	REGISTER_LUA_CFUNC(MarkerErasePosition);

	REGISTER_LUA_CFUNC(GetPlayerTraffic);

	lua_setglobal(L, "Spring");

	return true;
}


/******************************************************************************/
/******************************************************************************/

void CLuaUI::Shutdown()
{
	static const LuaHashString cmdStr("Shutdown");
	if (!cmdStr.GetGlobalFunc(L)) {
		return;
	}

	// call the routine
	RunCallIn(cmdStr, 0, 0);

	return;
}


void CLuaUI::GameFrame(int frameNumber)
{
	static const LuaHashString cmdStr("GameFrame");
	if (!cmdStr.GetGlobalFunc(L)) {
		return;
	}

	lua_pushnumber(L, frameNumber);

	// call the routine
	RunCallIn(cmdStr, 1, 0);

	return;
}


bool CLuaUI::ConfigCommand(const string& command)
{
	static const LuaHashString cmdStr("ConfigureLayout");
	if (!cmdStr.GetGlobalFunc(L)) {
		return true; // the call is not defined
	}

	lua_pushstring(L, command.c_str());

	// call the routine
	if (!RunCallIn(cmdStr, 1, 0)) {
		return false;
	}
	return true;
}


bool CLuaUI::AddConsoleLines()
{
	CInfoConsole* ic = game->infoConsole;
	if (ic == NULL) {
		return true;
	}

	vector<CInfoConsole::RawLine> lines;
	ic->GetNewRawLines(lines);

	const int count = (int)lines.size();
	for (int i = 0; i < count; i++) {
		const CInfoConsole::RawLine& rl = lines[i];

		static const LuaHashString cmdStr("AddConsoleLine");
		if (!cmdStr.GetGlobalFunc(L)) {
			return true; // the call is not defined
		}

		lua_pushstring(L, rl.text.c_str());
		lua_pushnumber(L, rl.zone);

		// call the function
		if (!RunCallIn(cmdStr, 2, 0)) {
			return false;
		}
	}
	return true;
}


bool CLuaUI::CommandNotify(const Command& cmd)
{
	static const LuaHashString cmdStr("CommandNotify");
	if (!cmdStr.GetGlobalFunc(L)) {
		return false; // the call is not defined
	}

	// push the command id
	lua_pushnumber(L, cmd.id);

	// push the params list
	lua_newtable(L);
	for (int p = 0; p < (int)cmd.params.size(); p++) {
		lua_pushnumber(L, p + 1);
		lua_pushnumber(L, cmd.params[p]);
		lua_rawset(L, -3);
	}

	// push the options table
	lua_newtable(L);
	HSTR_PUSH_NUMBER(L, "coded", cmd.options);
	HSTR_PUSH_BOOL(L, "alt",   !!(cmd.options & ALT_KEY));
	HSTR_PUSH_BOOL(L, "ctrl",  !!(cmd.options & CONTROL_KEY));
	HSTR_PUSH_BOOL(L, "shift", !!(cmd.options & SHIFT_KEY));
	HSTR_PUSH_BOOL(L, "right", !!(cmd.options & RIGHT_MOUSE_KEY));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?