In-Game Script Editor v0.2
I was going to start scripting my own gamemode when i realized that I would have to run and close the MTA to make the smallest change. (if there is another way tell me how )
I decided to develope a small in-client editor which could help me in my bugfixes and minor updates...
these are the editor's features:
File Browser (new)
Load Script
Save Script
Save and reload script
Toogle Chat [F1] (this feature lets you use your chat keys for writing)
Zipped Resource:
http://rapidshare.com/files/81600823/ScriptEditor.zip
In order for the File Browser work perfectly you must do the follwoing statemenst: (Mini-Tutorial written by eAi)
The scripts is divided in 3 parts, 1 client script and 2 server scripts.
Firstly, Ill give you the Client Script:
---------------In-Game Editor by Colex [Client Script]-------------------------
local WIDTH = 0.75
local HEIGHT = 0.9
local INITIAL_DIR = ""
--------------------
local canChat, editorWindow, editPath, scriptBox = true
local dialog = {}
local scriptInput = function()
if (guiGetVisible(editorWindow)) then
canChat = not(canChat)
toggleControl("chatbox", canChat)
end
end
local processReturn = function(ret, text)
outputChatBox(ret)
if (text) then
guiSetText(scriptBox, text)
end
end
local reloadScript = function(button, state)
if (button == "left" and state == "down") then
triggerServerEvent("onSaveScript", getRootElement(), guiGetText(editPath), guiGetText(scriptBox))
triggerServerEvent("onReloadScript", getRootElement())
end
end
local saveScript = function(button, state)
if (button == "left" and state == "down") then
triggerServerEvent("onSaveScript", getRootElement(), guiGetText(editPath), guiGetText(scriptBox))
end
end
local openScript = function(button, state, text)
if (button == "left" and state == "down") then
triggerServerEvent("onOpenScript", getRootElement(), guiGetText(editPath))
end
end
local toogleDialog = function(button, state)
if (dialog.window) and (state == "down") and (button == "left") then
guiSetVisible(dialog.window, not(guiGetVisible(dialog.window)))
guiBringToFront(dialog.window)
guiGridListClear(dialog.list)
guiGridListAddColumn(dialog.list, "Resources", 1)
triggerServerEvent("onRefreshDialog", getRootElement(), guiGetText(editPath))
end
end
local dialogSelect = function(button, state)
if (button == "left" and state == "down") then
local row = guiGridListGetSelectedItem(dialog.list)
if (row) then
local elem = guiGridListGetItemText(dialog.list, row, 1)
if (elem == "..\\") then elem = "" end
local pos, path = elem:find('%.') or 0
if (pos > 0) then
toogleDialog("left", "down")
path = getResourceNameFromPath(guiGetText(editPath)).."\\"..elem
else
path = elem
guiGridListClear(dialog.list)
guiGridListAddColumn(dialog.list, "Resources", 1)
triggerServerEvent("onRefreshDialog", getRootElement(), path)
end
guiSetText(editPath, path)
end
end
end
local dialogReturn = function(elem)
local row = guiGridListAddRow(dialog.list)
guiGridListSetItemText(dialog.list, row, 1, elem, false, false)
end
local createDialog = function()
if not(dialog.window) then
dialog.window = guiCreateWindow(0.01, 0.01, 0.5, 0.45, "Open Dialog", true)
local closeBtn = guiCreateButton(0.9, 0.15, 0.15, 0.15, "X", true, dialog.window)
dialog.list = guiCreateGridList(0.1, 0.15, 0.8, 0.85, true, dialog.window)
guiBringToFront(dialog.window)
guiSetVisible(dialog.window, false)
addEventHandler("onClientGUIClick", closeBtn, toogleDialog)
addEventHandler("onClientGUIDoubleClick", dialog.list, dialogSelect)
end
end
local createEditor = function()
if not(editorWindow) then --Constructor
editorWindow = guiCreateWindow(0.2, 0.2, HEIGHT, WIDTH, "In-Game Script Editor", true)
guiCreateLabel(0.05, 0.06, 1, 1, "Script Path:", true, editorWindow)
editPath = guiCreateEdit(0.04, 0.1, 0.6, 0.08, INITIAL_DIR, true, editorWindow)
local openBtn = guiCreateButton(0.75, 0.1, 0.2, 0.1, "Load Script", true, editorWindow)
local dialogBtn = guiCreateButton(0.65, 0.1, 0.1, 0.1, "...", true, editorWindow)
scriptBox = guiCreateMemo(0.02, 0.26, 0.96, 0.55, "", true, editorWindow)
local reloadBtn = guiCreateButton(0.75, 0.88, 0.2, 0.1, "Save & Reload", true, editorWindow)
local saveBtn = guiCreateButton(0.50, 0.88, 0.2, 0.1, "Save Script", true, editorWindow)
addEventHandler("onClientGUIClick", reloadBtn, reloadScript)
addEventHandler("onClientGUIClick", saveBtn, saveScript)
addEventHandler("onClientGUIClick", openBtn, openScript)
addEventHandler("onClientGUIClick", dialogBtn, toogleDialog)
bindKey("F1", "down", scriptInput)
createDialog()
showCursor(true)
else --Show/Hide
showCursor(not(guiGetVisible(editorWindow)))
guiSetVisible(editorWindow, not(guiGetVisible(editorWindow)))
guiSetVisible(dialog.window, false)
end
end
function getResourceNameFromPath(path)
if (type(path) ~= "string") then return "" end
local sep1, sep = path:find("\\") or 0
local sep2 = path:find("/") or 0
if (sep1 > sep2) then sep = sep1 else sep = sep2 end
if (sep == 0) then return path end
return path:sub(1, sep-1), path:sub(sep+1, path:len())
end
addCommandHandler ("editor", createEditor)
addEvent("onProcessReturn", true)
addEvent("onDialogReturn", true)
addEventHandler("onProcessReturn", getRootElement(), processReturn)
addEventHandler("onDialogReturn", getRootElement(), dialogReturn)
Now the Server Scripts:
---------------In-Game Editor by Colex [server Script]-------------------------
local getEndOfFile = function(file)
local tmp, endPos = fileGetPos(file)
while not fileIsEOF(file) do
fileRead(file, 500)
end
endPos = fileGetPos(file)
fileSetPos(file, tmp)
return endPos
end
function getResourceNameByPath(path)
if (type(path) ~= "string") then return "" end
local sep1, sep = path:find("\\") or 0
local sep2 = path:find("/") or 0
if (sep1 > sep2) then sep = sep1 else sep = sep2 end
if (sep == 0) then return path end
return path:sub(1, sep-1), path:sub(sep+1, path:len())
end
function reloadScript()
triggerClientEvent(client, "onProcessReturn", getRootElement(), "Restarting resources...")
local resources = getResources()
for _,res in ipairs(resources) do
if getResourceState(res) == "running" then
restartResource(res)
end
end
end
function saveScript(path, text)
triggerClientEvent(client, "onProcessReturn", getRootElement(), "Saving Script...")
local resName, path = getResourceNameByPath(path)
local file = fileCreate(path, getResourceFromName(resName))
if (file) then
fileWrite(file, text)
fileClose(file)
triggerClientEvent(client, "onProcessReturn", getRootElement(), "[DONE] Script Saved!")
else
triggerClientEvent(client, "onProcessReturn", getRootElement(), "[ERROR] Could not save the script!")
end
end
function openScript(path)
triggerClientEvent(client, "onProcessReturn", getRootElement(), "Loading Script...")
local resName, path = getResourceNameByPath(path)
local file = fileOpen(path, true, getResourceFromName(resName))
if (file) then
local text = fileRead(file, getEndOfFile(file))
triggerClientEvent(client, "onProcessReturn", getRootElement(), "[DONE] Script loaded!", text)
fileClose(file)
else
triggerClientEvent(client, "onProcessReturn", getRootElement(), "[ERROR] Script could not be loaded!")
end
end
addEvent("onReloadScript", true)
addEvent("onSaveScript", true)
addEvent("onOpenScript", true)
addEventHandler("onReloadScript", getRootElement(), reloadScript)
addEventHandler("onSaveScript", getRootElement(), saveScript)
addEventHandler("onOpenScript", getRootElement(), openScript)
---------------In-Game Editor by Colex [server Script (Open sDialog)]-------------------------
OpenDialog = {
create = function()
local resources, id = getResources(), #OpenDialog+1
return {res = resources, resource = "", refresh = OpenDialog.refresh, delete = OpenDialog.delete,
readMeta = OpenDialog.readMeta}
end,
refresh = function(self)
self.res = getResources()
end,
readMeta = function(self)
local root = getResourceFromName(self.resource)
local xml, ret = xmlLoadFile("meta.xml", root), {}
if (xml) then
local node, i = xmlFindSubNode(xml, "script", 0), 0
while (node) do
table.insert(ret, xmlNodeGetAttribute(node, "src"))
i = i + 1
node = xmlFindSubNode(xml, "script", i)
end
end
return ret
end,
delete = function(self)
for i in pairs(self) do
self[i] = nil
end
end
}
local refreshDialog = function(path)
OpenDial.resource = getResourceNameByPath(path)
local res, elems = getResourceFromName(OpenDial.resource), {}
if (res) then
elems = OpenDial:readMeta()
table.insert(elems, 1, "..\\")
else
elems = getResources()
end
for _,v in ipairs(elems) do
local value
if (type(v) == "userdata") then value = getResourceName(v) else value = v end
triggerClientEvent(client, "onDialogReturn", getRootElement(), value)
end
end
OpenDial = OpenDialog.create()
addEvent("onRefreshDialog", true)
addEventHandler("onRefreshDialog", getRootElement(), refreshDialog)
To open and close the editor type the command /editor
If you don't find it useful, you can still use it for studying purposes.
Anyway, hope you enjoy it, if you find any bug please report it here, so I can try to fix it.
Yours,
Colex