Jump to content

Dzsozi (h03)

Members
  • Posts

    696
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by Dzsozi (h03)

  1. Thank you for your help, I managed to fix this issue - and probably prevented some upcoming issues - by adding the following to the ACL: <acl> <group name="ServerScript"> <acl name="ServerScript"></acl> <object name="resource.*"></object> </group> <acl name="ServerScript"> <right name="function.loadstring" access="true"></right> ... </acl> </acl> Have a great day, thanks again @IIYAMA for your help and time!
  2. I saw it, but to be honest I couldn’t make up anything properly working so I postponded that project to rework the base of the systems and utilizations, I couldn’t figure out a way that I like and would use. So I started reworking my Lib resource to use the current concept in this topic. Thank you on that case very much, I will get back to it but I need this system finished first. Sorry if I came off rude for not replying, I didn’t mean to be. I already verified that the aclrequest has been accepted previously, i did this via console commands, but I would prefer if I didn’t have to assign a new aclrequest per resource, rather to work it easily and automatically. The server has been already restarted since the creation of this post and the issue is the same and still persists no matter if the aclrequest is there in the meta and accepted by an admin or not. So far I only noticed this issue inside shared and server side loadstrings. Is it possible that maybe I messed up something in my acl.xml settings? btw I didnt really use runcode before and don’t really see the point of it nor I really know what it is, like I script in/with files. After I made these changes I restarted the server entirely by closing the console terminal, and the same issue is present: As I said before, there's no such issue when using loadstring on client side scripts, I can manually and dynamically restart a resource and Lib resource if I change something in the Lib and it works as expected.
  3. Hi I want to create an easy utility / library resource where I would store functions that is used often but not provided in MTA by default. This resource, called Lib looks like this: Lib/ G_Libs.lua meta.xml libs/ C_dx.lua C_gui.lua C_screen.lua G_element.lua G_math.lua G_table.lua ... the meta.xml for the Lib resource: <meta> <info author="driphunnid" type="utility" name="Libs" /> <download_priority_group>3</download_priority_group> <min_mta_version client="1.6.0" server="1.6.0" /> <!-- <include resource="" /> --> <!-- a config must be an xml file, types: client or server --> <!-- <config src=".xml" type="client" /> <config src=".xml" type="server" /> --> <oop>true</oop> <!-- <settings> <setting name="" value="" /> </settings> --> <!-- <aclrequest> <right name="function.startResource" access="true" /> <right name="function.stopResource" access="true" /> </aclrequest> --> <!-- Shared --> <script src="libs/G_number.lua" type="shared" /> <script src="libs/G_string.lua" type="shared" /> <script src="libs/G_table.lua" type="shared" /> <script src="libs/G_color.lua" type="shared" /> <script src="libs/G_math.lua" type="shared" /> <script src="libs/G_vector.lua" type="shared" /> <script src="libs/G_matrix.lua" type="shared" /> <script src="libs/G_position.lua" type="shared" /> <script src="libs/G_rotation.lua" type="shared" /> <script src="libs/G_material.lua" type="shared" /> <script src="libs/G_bone.lua" type="shared" /> <script src="libs/G_weapon.lua" type="shared" /> <script src="libs/G_world.lua" type="shared" /> <script src="libs/G_element.lua" type="shared" /> <script src="libs/G_vehicle.lua" type="shared" /> <script src="libs/G_cfg.lua" type="shared" /> <!-- Client --> <script src="libs/C_screen.lua" type="client" /> <script src="libs/C_gui.lua" type="client" /> <script src="libs/C_dx.lua" type="client" /> <script src="libs/C_ped.lua" type="client" /> <script src="libs/C_vehicle.lua" type="client" /> <script src="G_Libs.lua" type="shared" /> <export function="load" type="shared" /> </meta> and the G_Libs.lua contains this simple fileReading logic - we return the content of a read file: LIBS_FOLDER = "libs" function load(name, side) -- side = prefix - client, server or shared / global - C, S, G assert(type(name) == "string", "Bad argument @'load' [Expected string at argument 1, got "..type(name).."]") side = type(side) == "string" and side or "G" local libPath = string.format("%s/%s_%s.lua", LIBS_FOLDER, side, name) assert(fileExists(libPath), "Library not found: " .. libPath .. " - you might need to specify a /different/ side (C, S, G).") local file = fileOpen(libPath) local content = fileRead(file, fileGetSize(file)) fileClose(file) return content end For example, content of libs/G_element.lua and C_screen.lua: C_screen.lua: SCREEN_SIZE = Vector2(guiGetScreenSize()) MEDIAN_SCREEN_SIZE = Vector2(1440, 900) function ssX(x) return x / MEDIAN_SCREEN_SIZE.x * SCREEN_SIZE.x end function ssY(y) return y / MEDIAN_SCREEN_SIZE.y * SCREEN_SIZE.y end function isCursorInPosition(x, y, width, height) if (not isCursorShowing()) then return false end local cx, cy = getCursorPosition() local cx, cy = (cx * SCREEN_SIZE.x), (cy * SCREEN_SIZE.y) return ((cx >= x and cx <= x + width) and (cy >= y and cy <= y + height)) end function isCursorInCircle(x, y, r) if (not isCursorShowing()) then return false end local cx, cy = getCursorPosition() local cx, cy = cx*SCREEN_SIZE.x, cy*SCREEN_SIZE.y return (x-cx)^2+(y-cy)^2 <= r^2 end G_element.lua: function isPlayer(element) if not isElement(element) then return false end if not (getElementType(element) == "player") then return false end return true end function isPed(element) if not isElement(element) then return false end if not (getElementType(element) == "ped") then return false end return true end function isCharacter(element) if not isElement(element) then return false end if not (isPed(element) or isPlayer(element)) then return false end if not (element.model == 0) then return false end return true end function isVehicle(element) if not isElement(element) then return false end if not (getElementType(element) == "vehicle") then return false end return true end function isObject(element) if not isElement(element) then return false end if not (getElementType(element) == "object") then return false end return true end function isBuilding(element) if not isElement(element) then return false end if not (getElementType(element) == "building") then return false end return true end When I use loadstring with this concept, it works as far as I use loadstring inside a client side script, other than that, when I try to load a lib using loadstring in a server or global / shared script, I get an Access denied error for "loadstring" and "call". Example - other test resource: C_test.lua (script type in xml is "client") loadstring(exports.Lib:load("element"))() -- loads the G_element.lua file contents from Lib/libs as expected loadstring(exports.Lib:load("screen", "C"))() -- loads the C_screen.lua file contents from Lib/libs as expected however if I change the script type from client to server or shared, I get an error from the test.lua: G_test.lua / S_test.lua (script type in xml is "shared" / "server") loadstring(exports.Lib:load("element"))() -- yields an error on resource start saying Access denied for loadstring and call I tried this setting in the test resource xml file and allowing the request via console for the resource, but same issue, still access denied: <aclrequest> <right name="function.loadstring" access="true" /> <right name="function.call" access="true" /> </aclrequest> Are there any workarounds or fixes for this issue? I really would like to use this concept, I've been coming into so many restriction errors lately, I feel like I can't fully do what I want and have potential for. Why does loadstring not work on shared and server side scripts, or what am I missing? This concept would make editing and using utility functions so much easier, nicer and simpler for me, I don't want to let go of this. Also I am planning to create a framework, a boilerplate "gamemode" engine, where you have so much utility functions and systems to use, that you'll only have to worry about the final gamemode concept you will be creating, this essentially will be a free open source multiplayer gta game engine, and this Lib resource would be a huge part of it. How can I make this work? Thank you for your time!
  4. Ahh, you are right, I totally forgot about this, I have had similar problems before because of this cloning behaviour. I get it that instead I should use an integer id, but previously in other systems where I did that, I got into so much work and big messy situations, because when I delete an existing POI dynamically (by script) for example I delete POI id 1, but there are other POIs with higher ids, then the whole table gets shifted down by one id and I can't use the same id to refer to the same POI for example with id 3 (because it becomes id 2 if i use table.remove), if the ids are static then it means that I should only make the id grow, then eventually the id would reach massive numbers like 213821, which I would like to avoid for the sake of simplicity. I could maybe use onClientKey I assume, but then how would I call the server side POIs interactionFunction? The interactionFunctions might also need parameters in some case like passing the player, for an inventory system, when a player interacts with a POI, give an item to the player, so on. What do you recommend, should I go with infinitely growing ID numbers which will reset only on resource restart or try to rework the whole POI system to be used with onClientKey? For some reason infinitely growing IDs seem unoptimized and unethical to me, that's why I did the collision element as an index, they are easy to look up and refer to based on a simple element. Also I don't really get what do you mean by making it lookupable by using another table ?
  5. What do you mean exactly? I just tested the code at this moment, as you already know, the system is in a shared script, and I create the test POI at client side, so far this works. I added an extra debug print in the PointOfInterest:create method: poi.interactionFunction = interactionFunction -- simplified print(type(poi.interactionFunction)) -- debugscript 3 says: function - note that I shouldn't be able to create the POI if it were not a function... poi.interactionFunction() -- chatbox says: "You are near the point of interest!" as the test poi is created onClientResourceStart Other than that I have a debug print for this function - located on client side: local function executePOIInteraction(key, state, poi, ...) print(inspect(poi)) poi.interactionFunction(...) return true end I also added a debug part when the colshape is hit on client side and getPOIFromColShape is used: addEventHandler("onClientColShapeHit", resourceRoot, function(hitElement, matchingDimension) if getElementType(hitElement) == "player" and matchingDimension then if hitElement == localPlayer then local poi = getPOIFromColShape(source) outputConsole(inspect(poi)) -- added for debug purposes if poi then if poi.onFootOnly and hitElement.vehicle then return end CURRENT_POI = poi bindKey(INTERACTION_KEY, "down", executePOIInteraction, CURRENT_POI) print("Key", INTERACTION_KEY, "bound to executePOIInteraction") end end end end) When I hit the colshape it says this: restart: Resource restarting... You are near the point of interest! { collision = elem:colshape2C61A570, dimension = 0, interactionFunction = <function 1>, -- ?????? interactionRadius = 1, interior = 0, onFootOnly = true, renderOffsetX = 0, renderOffsetY = 0, renderOffsetZ = 1, visibleDistance = 10, x = 195.00665283203, y = -141.83079528809, z = 1.5858917236328, <metatable> = <1>{ __index = <table 1>, create = <function 2>, destroy = <function 3>, getPlayersInRadius = <function 4>, isPlayerInRadius = <function 5> } } Clearly it is there, but why is it not when I use the key bind? The executePOIInteraction function is to use with the bindKey function when the player enters the colshape - however when this executes (I press "e" inside the colshape) it displays this: { collision = elem:colshape344AB8D8, dimension = 0, interactionRadius = 1, interior = 0, onFootOnly = true, renderOffsetX = 0, renderOffsetY = 0, renderOffsetZ = 1, visibleDistance = 10, x = 195.00665283203, y = -141.83079528809, z = 1.5858917236328 } and I get the error that I've been having; ERROR: InterestPoint\C_InterestPoint.lua:5: attempt to call field 'interactionFunction' (a nil value) What kind of other debug should I consider, it clearly fails unexpectedly for some reason and I can't figure out why where and when. When I restart the resource, you can see in the console that the testfunc is being executed properly, but not after, on demand, using the key bind.
  6. Yeah you are right, I didn't pay close enough attention to the first code. However in my opinion, constantly creating and destroying textures per element as they stream in/out makes a larger performance impact, rather than keeping all of the textures in memory and applying a texture replace shader when needed. As far as I know when you create or destroy a texture it makes an impact on the CPU, but when you apply or remove or use a shader it rather uses the resources of the GPU, which could handle more. In my opinion it would be better to just create every texture needed on the start of the resource. If you'd have 100+ vehicle paintjob textures to create and use later, it may freeze for a few seconds when starting the resource/script, but after that you will have access to all of them. Then you could handle the shader creating and destroying on streaming events, other than the texture creating and destroying. If you have 5 vehicle paintjob textures in high quality, and suddenly 5 HQ model/texture vehicle requires the creation of the HQ paintjob textures, a client might more likely to stutter when the 5 vehicles stream in/out at the same time. I think it is more efficient to store what you need in RAM and take a toll on the GPU, rather than constantly burdening the CPU. Correct me if I am wrong, but so far this is my understanding of how these kinds of things work.
  7. Every bit of code I posted above is what I have, additionally here is my current meta.xml to prove my setup. I also tried doing this script without the OOP scripting parts (like using metatable and such) but it still had the same result. The in-game print(inspect(poi)) function call from inside the executePOIInteraction doesn't display the variable and says there's no such thing as interactionFunction in the object. I also used the simplified method in the first place like you have now, but that didn't work either, that's why I somewhat forced the variable to be a function. My current meta.xml (I use a custom python script to generate the boilerplate resource files): <meta> <info author="driphunnid" type="utility" name="InterestPoint" /> <download_priority_group>3</download_priority_group> <min_mta_version client="1.6.0" server="1.6.0" /> <!-- <include resource="" /> --> <!-- a config must be an xml file, types: client or server --> <!-- <config src=".xml" type="client" /> <config src=".xml" type="server" /> --> <oop>true</oop> <!-- <settings> <setting name="" value="" /> </settings> --> <!-- <aclrequest> <right name="function.startResource" access="true" /> <right name="function.stopResource" access="true" /> </aclrequest> --> <!-- if download is false you can use downloadFile to download it later --> <!-- <file src="assets/" download="true" /> --> <script src="G_InterestPoint.lua" type="shared" /> <!-- <export function="" type="shared" /> --> <script src="C_InterestPoint.lua" type="client" /> <!-- <export function="" type="client" /> --> <script src="S_InterestPoint.lua" type="server" /> <!-- <export function="" type="server" /> --> <!-- <sync_map_element_data>false</sync_map_element_data> --> <!-- <map src=".map" dimension="0"/> --> </meta> Just for extra context (or if someone needs something like this) here is the python code used for resource files generation: import os def create_file(path, filename, content): """Create a file with the given content.""" with open(os.path.join(path, filename), 'w') as file: file.write(content) def main(): # Prompt for folder location folder_location = input("Paste the folder location here: ") # Check if the folder exists if not os.path.isdir(folder_location): print("Folder does not exist, please check the path and try again.") return # Get the name of the folder folder_name = os.path.basename(folder_location) # If a meta.xml file already exists, ask if the user wants to overwrite it if os.path.isfile(os.path.join(folder_location, "meta.xml")): overwrite = input("A meta.xml file already exists with possibly other resource files. Do you want to overwrite it? (y/n): ") if overwrite.lower() != "y": print("Operation cancelled.") return print() # Prompt for script type - utility, main, system print("Script types: utility, main, system, other (anything custom, you don't have to use 'other')") print("'utility' download group is 3, 'main' is 2, 'system' is 1, and anything other is 0.") script_type = input("Enter the script type: ") # Set download priority group based on script type if script_type == "utility": download_priority_group = 3 elif script_type == "main": download_priority_group = 2 elif script_type == "system": download_priority_group = 1 else: download_priority_group = 0 # File contents (customize as needed) contents = { "C_" + folder_name + ".lua": ''' -- Implement your script addEventHandler("onClientResourceStart", resourceRoot, function() return true end) addEventHandler("onClientResourceStop", resourceRoot, function() return true end) ''', "S_" + folder_name + ".lua": ''' -- Implement your script addEventHandler("onResourceStart", resourceRoot, function() return true end) addEventHandler("onResourceStop", resourceRoot, function() return true end) ''', "G_" + folder_name + ".lua": '', "meta.xml": ''' <meta> <info author="driphunnid" type="''' + script_type + '''" name="''' + folder_name + '''" /> <download_priority_group>''' + str(download_priority_group) + '''</download_priority_group> <min_mta_version client="1.6.0" server="1.6.0" /> <!-- <include resource="" /> --> <!-- a config must be an xml file, types: client or server --> <!-- <config src=".xml" type="client" /> <config src=".xml" type="server" /> --> <oop>true</oop> <!-- <settings> <setting name="" value="" /> </settings> --> <!-- <aclrequest> <right name="function.startResource" access="true" /> <right name="function.stopResource" access="true" /> </aclrequest> --> <!-- if download is false you can use downloadFile to download it later --> <!-- <file src="assets/" download="true" /> --> <script src="G_''' + folder_name + '''.lua" type="shared" /> <!-- <export function="" type="shared" /> --> <script src="C_''' + folder_name + '''.lua" type="client" /> <!-- <export function="" type="client" /> --> <script src="S_''' + folder_name + '''.lua" type="server" /> <!-- <export function="" type="server" /> --> <!-- <sync_map_element_data>false</sync_map_element_data> --> <!-- <map src=".map" dimension="0"/> --> </meta>''', } # Create files for filename, content in contents.items(): create_file(folder_location, filename, content) print(f"Created {filename}") # Create a folder for the resources, assets, etc. os.makedirs(os.path.join(folder_location, "assets")) print("Created 'assets' folder") if __name__ == "__main__": main() I am not entirely sure what am I missing or doing wrong, I've done similar systems before where I had to pass a function type as parameter for later execution, there were no problems like this previously. And as I wrote, currently the main POI object creation system is located in the G_InterestPoint.lua which is a shared / global script inside the resource, but I tried changing it to client side to see if that is the cause of the problem, but no.
  8. 2nd seems more sophisticated and more likely to be performance friendly since it somewhat has logic for ElementStreamIn event, however it'd need more checks to avoid unnecessarily calling the applyTexture function (like check if the vehicle already has it applied, handle ElementStreamOut as well, etc etc.)
  9. there are no such events as onElementCollide onElementLeaveCollide https://wiki.multitheftauto.com/wiki/Client_Scripting_Events#Element_events https://wiki.multitheftauto.com/wiki/Server_Scripting_Events#Element_events I think the best thing you could do for this case is either a distance check, or creating collision shapes alongside the objects you need the check against. You maybe could achieve more precise results with a distance check logic, since you could get the position of a vehicle dummy or ped bone and many more, but you'd need to do it in a render event, or an event that is not as heavy as a render, but still constantly called, like onClientPedsProcessed.
  10. Hi, I am doing a point of interest system, where it is possible to create literal "points" of interest to draw on the screen and interact with. Everything I did works as I wanted to, except one thing where the interactionFunction doesn't get saved in the object, therefore I can't execute it for some reason. I did the object creation system inside a shared script to be able to create POIs both client and server side, and I want to code additional client and server side handling for when to bind and execute the interactionFunction. Here are my codes so far, G_InterestPoint.lua: INTERACTION_KEY = "e" -------------------------------------------------------------------------- -------------------------------------------------------------------------- -------------------------------------------------------------------------- PointOfInterest = {} PointOfInterest.__index = PointOfInterest TBL_POIS = {} function getPointsOfInterest() return TBL_POIS end function PointOfInterest:create(x, y, z, interactionRadius, interactionFunction, visibleDistance, interior, dimension, renderOffsetX, renderOffsetY, renderOffsetZ, onFootOnly) if type(x) ~= "number" or type(y) ~= "number" or type(z) ~= "number" then error("Bad argument @ PointOfInterest:create [Expected number at argument 1, 2, 3, got "..type(x)..", "..type(y)..", "..type(z).."]", 2) end if type(interactionFunction) ~= "function" then error("Bad argument @ PointOfInterest:create [Expected function at argument 5, got "..type(interactionFunction).."]", 2) end local poi = {} setmetatable(poi, PointOfInterest) poi.x = x poi.y = y poi.z = z poi.interactionRadius = type(interactionRadius) == "number" and interactionRadius or 1 poi.collision = createColSphere(x, y, z, poi.interactionRadius) poi.collision:setID("poi") -- Set the ID to "poi" to identify it as a point of interest poi.interactionFunction = function(...) return interactionFunction(...) end poi.visibleDistance = type(visibleDistance) == "number" and visibleDistance or 10 poi.interior = type(interior) == "number" and interior or 0 poi.dimension = type(dimension) == "number" and dimension or 0 poi.renderOffsetX = type(renderOffsetX) == "number" and renderOffsetX or 0 poi.renderOffsetY = type(renderOffsetY) == "number" and renderOffsetY or 0 poi.renderOffsetZ = type(renderOffsetZ) == "number" and renderOffsetZ or 0 poi.onFootOnly = (type(onFootOnly) == "boolean" and onFootOnly) or false TBL_POIS[poi.collision] = poi return poi end function PointOfInterest:destroy() TBL_POIS[self.collision] = nil destroyElement(self.collision) return true end function PointOfInterest:getPlayersInRadius() local players = {} for i, player in ipairs(getElementsWithinColShape(self.collision, "player")) do if player.interior == self.interior and player.dimension == self.dimension then table.insert(players, player) end end return players end function PointOfInterest:isPlayerInRadius(player) if not isElement(player) then error("Bad argument @ PointOfInterest:isPlayerInRadius [Expected element at argument 1, got "..type(player).."]", 2) end if getElementType(player) ~= "player" then error("Bad argument @ PointOfInterest:isPlayerInRadius [Expected player at argument 1, got "..getElementType(player).."]", 2) end if player.interior ~= self.interior or player.dimension ~= self.dimension then return false end return isElementWithinColShape(player, self.collision) end -------------------------------------------------------------------------- -------------------------------------------------------------------------- -------------------------------------------------------------------------- function getPOIFromColShape(colshape) if not isElement(colshape) then error("Bad argument @ getPOIFromColShape [Expected element at argument 1, got "..type(colshape).."]", 2) end if getElementType(colshape) ~= "colshape" then error("Bad argument @ getPOIFromColShape [Expected colshape at argument 1, got "..getElementType(colshape).."]", 2) end return TBL_POIS[colshape] end C_InterestPoint.lua: local CURRENT_POI = nil local function executePOIInteraction(key, state, poi, ...) print(inspect(poi)) poi.interactionFunction(...) return true end addEventHandler("onClientColShapeHit", resourceRoot, function(hitElement, matchingDimension) if getElementType(hitElement) == "player" and matchingDimension then if hitElement == localPlayer then local poi = getPOIFromColShape(source) if poi then CURRENT_POI = poi bindKey(INTERACTION_KEY, "down", executePOIInteraction, CURRENT_POI) print("Key", INTERACTION_KEY, "bound to executePOIInteraction") end end end end) addEventHandler("onClientColShapeLeave", resourceRoot, function(leaveElement, matchingDimension) if getElementType(leaveElement) == "player" and matchingDimension then if leaveElement == localPlayer then if CURRENT_POI then CURRENT_POI = nil unbindKey(INTERACTION_KEY, "down", executePOIInteraction) print("Key", INTERACTION_KEY, "unbound") end end end end) -------------------------------------------------------------------------- -------------------------------------------------------------------------- -------------------------------------------------------------------------- addEventHandler("onClientRender", root, function() for colshape, data in pairs(getPointsOfInterest()) do local distance = getDistanceBetweenPoints3D(data.x, data.y, data.z, localPlayer.position.x, localPlayer.position.y, localPlayer.position.z) local alphaFade = math.min(255, math.max(0, 255 - ((distance - (data.visibleDistance * 0.7)) / (data.visibleDistance * 0.3)) * 255)) if distance <= data.visibleDistance then local sx, sy = getScreenFromWorldPosition(data.x + data.renderOffsetX, data.y + data.renderOffsetY, data.z + data.renderOffsetZ) if sx and sy then local circleColorIn = tocolor(100, 200, 255, alphaFade) local circleColorOut = tocolor(100, 200, 255, alphaFade) if isElementWithinColShape(localPlayer, colshape) then if not (data.onFootOnly and localPlayer.vehicle) then circleColorOut = tocolor(255, 255, 255, alphaFade) end end dxDrawCircle(sx, sy, 8, 0, 360, circleColorOut, circleColorIn, 8, 1, false) end end end end) function testfunc() outputChatBox('You are near the point of interest!') return true end addEventHandler("onClientResourceStart", resourceRoot, function() local test = PointOfInterest:create(195.00665283203, -141.83079528809, 1.5858917236328, 1, testfunc, 10, 0, 0, 0, 0, 1, true) return true end) addEventHandler("onClientResourceStop", resourceRoot, function() return true end) (I don't have server side bind and execution logic done yet) This client side POI is at blueberry behind the pizza stack, between the pizza place and the motel. When I go inside it and press E, it is visible that the poi object doesn't have the interactionFunction variable, and I get an error saying: ERROR: InterestPoint\C_InterestPoint.lua:5: attempt to call field 'interactionFunction' (a nil value) I tried everything, putting the G_InterestPoint.lua from shared to client in the meta, I tried making the poi.interactionFunction as poi.interactionFunction = function(...) return interactionFunction(...) end but none of it works, yields the same error. What is the reason behind this behaviour? Why I can't store the function as a variable through a function exectuion? The strangest thing is that I shouldn't be able to create the POI object at the first place if the interactionFunction were not a function type parameter. Thank you for the help in advance!
  11. I uninstalled openssl version I had which was 3.0, then I installed 1.1.1 from source as you told, now I get these errors: openssl-1.1.1k$ openssl version openssl: /lib/x86_64-linux-gnu/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by openssl) openssl: /lib/x86_64-linux-gnu/libcrypto.so.1.1: version `OPENSSL_1_1_1' not found (required by openssl) openssl: /lib/x86_64-linux-gnu/libcrypto.so.1.1: version `OPENSSL_1_1_0' not found (required by openssl) openssl: /lib/x86_64-linux-gnu/libcrypto.so.1.1: version `OPENSSL_1_1_0d' not found (required by /lib/x86_64-linux-gnu/libssl.so.1.1) openssl: /lib/x86_64-linux-gnu/libcrypto.so.1.1: version `OPENSSL_1_1_0f' not found (required by /lib/x86_64-linux-gnu/libssl.so.1.1) openssl: /lib/x86_64-linux-gnu/libcrypto.so.1.1: version `OPENSSL_1_1_0' not found (required by /lib/x86_64-linux-gnu/libssl.so.1.1) Yea I know, I didn't bother to change it yet. What should I do?
  12. @Laxante101 Should I remove my current OpenSSL version first? EDIT: I launched the commands without removing my current version, however as I stated in my original post, I already installed an ubuntu archive .deb package previously which installed libssl.so.1.1 previously. But the result of launching the commands: libssl1.1 is already the newest version (1.1.0g-2ubuntu4). 0 updated, 0 installed, 0 to be removed, and 14 not updated. hmsvr@server-pc:~$ ls -l /lib/x86_64-linux-gnu/libssl.so.1.1 -rw-r--r-- 1 root root 433760 apr 25 2018 /lib/x86_64-linux-gnu/libssl.so.1.1 EDIT 2: I removed the current libssl.so.1.1 from the /lib/x86_64-linux-gnu/ directory, i also purged libssl1.1, then tried to install it using your command but it won't let me, it says the package is old: hmsvr@server-pc:~$ sudo apt install libssl1.1 Reading packing lists... Done Building dependency tree... Done Reading status information... Done package libssl1.1 is not available but is referenced by another. The requested package is missing, outdated or only available from another source E: package "libssl1.1" has no version marked for installation EDIT 3: I tried fking around again with the .so files as I had to, every 1.1 .so file is in location, but I still get the error about OPENSSL_1_1_1 and I can't install the openssl 1.1 version for some reason, I tried removing and purging every current openssl thing, but it would still say this: hmsvr@server-pc:~$ sudo apt-get install openssl1.1 Reading packing lists... Done Building dependency tree... Done Reading status information... Done Note: Select "libengine-gost-openssl1.1" for "openssl1.1" regex Note: select "libengine-pkcs11-openssl1.1" for regex "openssl1.1" Note: select "apache2-api-20120211-openssl1.1" for regex "openssl1.1" Note: select "apache2-bin" instead of "apache2-api-20120211-openssl1.1" libengine-gost-openssl1.1 is now the latest version (1.1.0.3-1ubuntu1). apache2-bin is now the latest version (2.4.52-1ubuntu4.12). libengine-pkcs11-openssl1.1 is now the latest version (0.4.11-1ubuntu0.22.04.1). 0 updated, 0 newly installed, 0 to be removed and 14 not updated. and in the MTA SA console I get this: restart database [20:31:30] restart: Requested by Console [20:31:30] restart: Resource restarting... [20:31:30] Stopping Database [20:31:30] Starting Database [20:31:30] ERROR: Could not load /home/hmsvr/ftp/servers/LegendaryLegacy/SA/x64/ dbconmy.so - /lib/x86_64-linux-gnu/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by /home/hmsvr/ftp/servers/LegendaryLegacy/SA/x64/dbconmy.so) [20:31:30] WARNING: [Engine]/[Main]/Database/S_Database.lua:17: Bad usage @ 'dbConnect' [Could not connect] [20:31:30] ERROR: [Engine]/[Main]/Database/S_Database.lua:27: Database connection failed; retrying in 5 seconds [20:31:30] Database restarted successfully The openssl version command returns this: hmsvr@server-pc:~$ openssl version -bash: /usr/bin/openssl: No such file or directory Currently I removed openssl again, but I all along this time I've had the 3.0.2 version and could only install it via sudo apt install openssl
  13. Hello! I have a local network home server (192.168.0.4) for storage and other service server running. On this server I run Ubuntu server with CasaOS. I recently made two custom flask apps, one for a XAMPP manager and one for an MTA Server Manager so I can easily have a web UI on two different ports. I setup everything successfully, I could run and join to an FTP server from my main desktop PC (192.168.0.122) or laptop, manage MTA servers correctly, start and stop them, join them, open and run phpMyAdmin. But when I got to the part to run the MTA server on the server PC, and setup the MySQL database connection I run into an issue regarding linux. [02:25:51] Starting Database [02:25:51] ERROR: Could not load /home/hmsvr/ftp/servers/LegendaryLegacy/SA/x64/dbconmy.so - /lib/x86_64-linux-gnu/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by /home/hmsvr/ftp/servers/LegendaryLegacy/SA/x64/dbconmy.so) [02:2 5:51] WARNING: [Engine]/[Main]/Database/S_Database.lua:17: Bad usage @ 'dbConnect' [Could not connect] [02:25:51] ERROR: [Engine]/[Main]/Database/S_Database.lua:27: Database connection failed; When I start the server on my desktop PC, but still use the server PC to run the Apache, MySQL and FTP, I can successfully connect to the MySQL server running on my server PC. G_Database.lua & S_Database.lua sections for context DATABASE_DETAILS = { ["host"] = "192.168.0.4", -- "127.0.0.1" or "localhost" if the mysql server - XAMPP - runs on your PC, or "your server ip" if you have a separate PC or VPS ["port"] = 3306, -- Provided in XAMPP control panel or my.ini / my.cnf ["username"] = "mysql", -- Provided in phpMyAdmin or my.ini / my.cnf ["password"] = "", -- Provided in phpMyAdmin or my.ini / my.cnf - none by default ["database"] = "mta-ll", -- Rename if you are using different database or create one with this name } ---------------------- DATABASE = { CONNECTION = nil, RECONNECT_TIMER = nil } function connectDatabase() DATABASE.CONNECTION = dbConnect("mysql", "dbname="..DATABASE_DETAILS["database"]..";host="..DATABASE_DETAILS["host"]..";port="..DATABASE_DETAILS["port"], DATABASE_DETAILS["username"], DATABASE_DETAILS["password"], "log=1") if DATABASE.CONNECTION then print("Database connection successful") if isTimer(DATABASE.RECONNECT_TIMER) then killTimer(DATABASE.RECONNECT_TIMER) end DATABASE.RECONNECT_TIMER = nil --prepareDatabase() return true else error("Database connection failed; retrying in 5 seconds") DATABASE.RECONNECT_TIMER = setTimer(function() connectDatabase() end, 5000, 1) return false end end function disconnectDatabase() if not DATABASE.CONNECTION then return false end DATABASE.CONNECTION = nil print("Database connection closed") if isTimer(DATABASE.RECONNECT_TIMER) then killTimer(DATABASE.RECONNECT_TIMER) end DATABASE.RECONNECT_TIMER = nil return true end addEventHandler("onResourceStart", resourceRoot, function() connectDatabase() return true end) addEventHandler("onResourceStop", resourceRoot, function() disconnectDatabase() return true end) I already had OpenSSL installed when I checked the version, but also my version is 3.0 something. I was looking on many forums on how to get OpenSSL 1.1.1 as the error message requires but I didn't find any easy solutions apart from building from source and many complicated commands which I am not sure how to revert if it doesn't solve the issue. I downloaded some .deb file from ubuntu archive and istalled it via a forum post but I don't remember which one was it, because at first I got an error message saying that the libssl.so1.1 directory didn't exist or something similar, that's why I then tried to install that but then realised I have a newer OpenSSL version. I didn't even know I will have to f*ck around with OpenSSL for the sake of MTA SA MySQL database handling, nor I had to do this previously - well previously I didn't use MTA Linux Server on linux either. Does anybody have any suggestions how could I possibly solve this issue so I am able to run the linux version of MTA server on my home network Ubuntu linux server alongside the XAMPP / LAMPP Apache MySQL and FTP servers? I followed the tutorial on the MTA SA Linux Server Tutorial page. This is currently the only thing keeping me away from finishing what I've been wanting to do for a long time for a home network MTA development environment to be able to store and access and edit the server files on a separate server PC from various other devices. I am planning on releasing the flask apps for the XAMPP and MTA server managers later on in case anybody needs something similar, or also it could be used as good templates if you want to create docker images from it or so on, however the code may not be production ready but will be free to use and adjust. Thank you for your time response and help in advance!
  14. Dzsozi (h03)

    Crash

    Hello, I recently had this same issue and I managed to find what is causing it, here is my crash report: Version = 1.6-release-22684.0.000 Time = Tue Sep 10 15:51:23 2024 Module = D:\Games\MTA San Andreas\mods\deathmatch\client.dll Code = 0xC0000005 Offset = 0x000E19B2 EAX=00000000 EBX=0177F8CC ECX=28191E60 EDX=00000038 ESI=29DF240C EDI=220B8F90 EBP=0177F86C ESP=0177F86C EIP=5BBF19B2 FLG=00010202 CS=0023 DS=002B SS=002B ES=002B FS=0053 GS=002B it is almost exactly the same. In my case the cause of the crash is the default play resource that I currently have (I didn't try to update it yet). To me it seems like there is a client side scirpt to be more exact, because the crash happens either when disconnecting from the server, or while on the server and stopping the play resource. So I assume in some script during the "onClientResourceStop" event something makes the client crash. I didn't have this problem earlier (months, years before), I was using the play resource temporarily to just move around and spawn cars and such for my projects. So the fix to the problem - if you are the server owner remove or don't start the freeroam / play resource or try to download a newer version of it if available. I believe there is also an 'upgrade' command in MTA server, so you can try to 'upgrade play' but that only said to me that: ERROR: Problem with resource: play; Upgrade completed. If you are not the owner of the server all you can do is notify the server owners of the problem, maybe redirect them to this forum page so they can check if the play resource causes the problem for them as well, ask other players if they have this problem, or just choose an other server to play on. Hope this helps you and many others, good luck!
  15. Thank you, I didn't know I could do this with getElementsByType ?
  16. This is a great idea and would be much simpler and easier indeed, now that you said I realised it. But I think the reason I wanted to do a scanning type solution is because of the custom placed objects (i know I can check those and I already did in the original script), but also, more likely because of the removed world models. What would you suggest to check that, if I were doing the solution you mentioned? I have some custom maps which for sure remove some lamps, I made some that removes even a whole street.
  17. Sorry for bumping this topic that late, I got some free time now, I still wasn’t able to finish this project based on the examples, also I just realised that the scan will be going diagonally if I add to x and y at the same time, therefore the scan wouldn’t apply to the whole world. I would like to achieve an effect of scanning such as from the top left corner of the map to the bottom right, going sideways, and when the camera reaches the right side, it snaps back to the left and gets offset on the y axis. I am not sure about how to achieve this between the range of -3000 to 3000 on the x and y axis inside a coroutine function with loops, am I even doing it the right way by using for loop? I would have to prevent the loop from happening on the y axis before the scanX reaches the right side. Right now I can’t send my current code and I can’t remember what errors I got, I’m at work but I wanted to reply and let you know that I’m still interested and trying to fix & get it done. I will post my code asap, could you please maybe help me finishing and correcting it?
  18. Thank you for teaching me, really, I tried to make the scanning with these functions, I get an error spam "cannot resume dead coroutine" because of the timer (this line) STREET_LIGHTS.SCAN_TIMER = setTimer(resumeScan, 1000, 0) Here's my current code, could you help me with what am I doing wrong? local STREET_LIGHTS = { VALID_MODELS = { [1294] = {name = "mlamppost", offsets = {Vector3(0,0.3,1)}, radius = {start = 0.075, stop = 50}}, [1297] = {name = "lamppost1", offsets = {Vector3(0,0.3,1)}, radius = {start = 0.075, stop = 50}}, [1290] = {name = "lamppost2", offsets = {Vector3(3,0.03,5.4), Vector3(-3,0.03,5.4)}, radius = {start = 0.075, stop = 75}}, [1226] = {name = "lamppost3", offsets = {Vector3(-1.3,0.165,3.675)}, radius = {start = 0.075, stop = 50}}, }, OBJECT_LIGHTS = {}, } local SCAN = { current = Vector2(-3000, -3000), } local SCAN_WORLD = coroutine.create(function() for x = SCAN.current.x, 3000, 10 do if math.abs(x) % 100 == 100 then SCAN.current.x = x print"yield" coroutine.yield() end for y = SCAN.current.y, 3000, 10 do if SCAN.current.x >= 3000 and SCAN.current.y >= 3000 then if isTimer(STREET_LIGHTS.SCAN_TIMER) then killTimer(STREET_LIGHTS.SCAN_TIMER) end STREET_LIGHTS.SCAN_TIMER = nil setCameraTarget(localPlayer) coroutine.yield() break end if math.abs(y) % 100 == 100 then SCAN.current.y = y coroutine.yield() end setCameraMatrix(x, y, 500, x, y, 0) local hit, _,_,_,_,_,_,_,_,_,_,worldModelID,worldX,worldY,worldZ,worldRotX,worldRotY,worldRotZ,_ = processLineOfSight( x, y, 500, x + 5, y + 5, 0, true, false, false, true, false, false, false, false, nil, true, false ) if hit then --if STREET_LIGHTS.VALID_MODELS[worldModelID] then print(worldModelID) -- do i actually get the models on screen? i get some numbers for sure but camera is stuck and position is not updating --end end end end return true end) local function resumeScan() return coroutine.resume(SCAN_WORLD) end addEventHandler("onClientResourceStart", resourceRoot, function() if not isTimer(STREET_LIGHTS.SCAN_TIMER) then STREET_LIGHTS.SCAN_TIMER = setTimer(resumeScan, 1000, 0) end return true end) And actually I don't even get the "yield" output as expected from this line: if math.abs(x) % 100 == 100 then SCAN.current.x = x print"yield" coroutine.yield() end Camera is stuck at one place on the top right corner of the map and first I get a bunch of spam of 3 or 4 numbers, then the error about cannot resume dead coroutine.
  19. Sorry I didn’t make time to reply, my fault. Actually it is not so clear, I don’t really know how to use coroutine functions, I never did before. Not so sure how to implement it for the purpose I need. Thank you for the advice I didn’t even think about that and actually makes sense to do it.
  20. Hello! I would like to get the positions of all the lampposts. I was trying to use processLineOfSight to achieve this, since getElementsByType("object") doesn't return default world objects. I tried using a loop from 0 to 3000 on the x and y axis, but I get an infinite running script error. Why do I get this error and how could I achieve a scan on the world? Here's my current code: (I commented out most parts while trying to find the cause of the problem, so I would only see the positions of all the lamps if the scan was successful) local STREET_LIGHTS = { VALID_MODELS = { [1294] = {name = "mlamppost", offsets = {Vector3(0,0.3,1)}, radius = {start = 0.075, stop = 50}}, [1297] = {name = "lamppost1", offsets = {Vector3(0,0.3,1)}, radius = {start = 0.075, stop = 50}}, [1290] = {name = "lamppost2", offsets = {Vector3(3,0.03,5.4), Vector3(-3,0.03,5.4)}, radius = {start = 0.075, stop = 75}}, [1226] = {name = "lamppost3", offsets = {Vector3(-1.3,0.165,3.675)}, radius = {start = 0.075, stop = 50}}, }, OBJECT_LIGHTS = {}, } function processStreetLights() for x = 0, 3000, 5 do for y = 0, 3000, 5 do local hit, _,_,_,_,_,_,_,_,_,_,worldModelID,worldX,worldY,worldZ,worldRotX,worldRotY,worldRotZ,_ = processLineOfSight( x, y, 0, x + 5, y + 5, 500, true, false, false, true, false, false, false, false, nil, true, false ) if hit then --[[if STREET_LIGHTS.VALID_MODELS[worldModelID] then local data = STREET_LIGHTS.VALID_MODELS[worldModelID] local searchlights = {} for i, offset in pairs(data.offsets) do local startPos = Vector3(worldX, worldY, worldZ + offset.z) --Vector3(exports["sa_utility"]:getPositionFromElementOffset(obj, offset.x, offset.y, offset.z)) startPos.x = worldX + math.sin( math.rad( worldRotZ ) ) * offset.x startPos.y = worldY + math.cos( math.rad( worldRotZ ) ) * offset.y local endPos = startPos --Vector3(exports["sa_utility"]:getPositionFromElementOffset(obj, offset.x, offset.y, 0.25)) endPos.z = worldZ + 0.25 searchlights[i] = SearchLight(startPos, endPos, data.radius.start, data.radius.stop, true) end --STREET_LIGHTS.OBJECT_LIGHTS[obj] = searchlights table.insert(STREET_LIGHTS.OBJECT_LIGHTS, searchlights) end]] print(worldX, worldY, worldZ) end end end --[[for k, obj in pairs(getElementsByType("object")) do if STREET_LIGHTS.VALID_MODELS[obj.model] then local data = STREET_LIGHTS.VALID_MODELS[obj.model] local searchlights = {} for i, offset in pairs(data.offsets) do local startPos = Vector3(exports["sa_utility"]:getPositionFromElementOffset(obj, offset.x, offset.y, offset.z)) local endPos = Vector3(exports["sa_utility"]:getPositionFromElementOffset(obj, offset.x, offset.y, 0.25)) searchlights[i] = SearchLight(startPos, endPos, data.radius.start, data.radius.stop, true) end STREET_LIGHTS.OBJECT_LIGHTS[obj] = searchlights end end]] return true end addEventHandler("onClientResourceStart", resourceRoot, function() processStreetLights() return true end) Thank you for help in advance!
  21. It is working and the text is drawn, the problem is that you are setting the text position outside of the render target canvas size. When you are drawing inside a render target, the positions start from 0 again. textureWidth, textureHeight = 100, 50 texture = dxCreateRenderTarget(textureWidth, textureHeight, true) dxSetRenderTarget(texture, true) dxDrawText("text", 5, 5, textureWidth, textureHeight) dxSetRenderTarget() dxDrawImage(posx, posy, textureWidth, textureHeight, texture) This will draw the render target as an image wherever you want, and inside of it will be the text on the top left corner, offset by 5 pixels.
  22. Thank you so much, it works and I also managed to do the step 4 to manage remaining items, so I can add to main inventory or drop them. I appreciate it and your time
  23. Hello! I started re-doing my inventory system, I made some functions based on this topic I did everything without a problem, everything works fine, except a calculation I am trying to do when giving an item to a container. I have stack limits defined for items inside an ITEM_TABLE. The stack limit for, let's say Apple item is 5. When calling the giveItem function, I would like to check if the count exceeds the stack limit, then loop the item giving process until the newly calculated count value is less than the stack limit. So let's say I call -- itemID, count giveItem(1, 8) -- give 8 apples, but the apple has a stack limit of 5, so I would like the player to end up with 2 apple items, one with a count of 5 and one with a count of 3 So then I would like the player to have 2 different apple items, one with a count of 5 and one with a count of 3 This is how I was trying to do it, but it seems like I can't use the repeat until/while loop properly, or I am missing calculations, I can't get the result I want. function ContainerMethods:giveItem(itemID, count) local itemDetails = getItemDetails(itemID) if not itemDetails then return false end count = tonumber(count) or 1 local carrySlot = self:findExistingItemSlot(itemID) if carrySlot and carrySlot.count + count <= itemDetails.stacklimit then -- if the container has an item like this and it's less than the stack limit, add the count carrySlot.count = carrySlot.count + count else local tempCount = count repeat -- i don't know if i should use repeat until, or while loop, repeat until seems like the correct way of doing it --while tempCount > itemDetails.stacklimit do local slotX, slotY = self:findFreeSlotForItem(itemID) if slotX and slotY then -- i am working with a grid inventory with different item sizes for x = slotX, slotX + itemDetails.size.x - 1, 1 do for y = slotY, slotY + itemDetails.size.y - 1, 1 do self.grid[x][y] = true end end local newItem = { ["itemID"] = itemID, ["count"] = tempCount, -- should i make calculations here as well?? i don't think so but i could be wrong ["slot"] = {x = slotX, y = slotY}, } table.insert(self.items, newItem) tempCount = tempCount - itemDetails.stacklimit -- tempCount is the difference print(tempCount) else print("no empty space for item '" .. itemID .. "' in container '" .. self.name .. "'") return false end --end until tempCount < itemDetails.stacklimit -- repeat adding a new item until the count is less than the stack limit end return true end But the result I get is: Notice that the debugscript prints 3, but my inventory has only one item with the count of 8, instead of 5 and 3. How can I make this function properly, so I don't have to worry about it in the future when I give an item to the player? Thank you for your help in advance!
  24. Sorry for not responding, meanwhile I solved the problem and this topic went unnoticed by me. I solved it by using Kam's updated scripts made by gold_fish ([REL] KAM's GTA Scripts (2018) / UPD: 31.05.2020 / - Tools - GTAForums). I read that this updated script supports exporting and importing normals and also reflections, therefore the problems were solved. Also I think I had some issues with the model itself, I was playing around with the smoothing groups and etc. Using the updated scripts solves the problem, however I will have to remake my model tho. This topic can be locked.
  25. setElementData might come handy in these cases. Good luck with scripting!
×
×
  • Create New...