Kenneth Posted December 8, 2022 Posted December 8, 2022 When I get the player class getPlayer() then I want to index a field it gives me nil. Why can't I index fields from class but only methods? Example The java IsoPlayer closestZombie field in a public float But in a lua script below getPlayer().closestZombie --Gives me nil
Kenneth Posted December 8, 2022 Author Posted December 8, 2022 (edited) A Solution I found was --Doesn't work on private java fields local indexOfField = 21 --CanHearAll local player = getPlayer() local field = getClassField(player,indexOfField) local value = getClassFieldVal(player, field) print(value) To get the index of field 0 then count in the java class files until you reach your field I wrote a function that does this for you and get field local function getField(class, fieldName) local i = 0 while true do local field = getClassField(class,i) if field:getName() == fieldName then return getClassFieldVal(class,field) end i = i + 1 end end print(getField(getPlayer(), "closestZombie")) Edited December 8, 2022 by Kenneth Tchernobill 1
stuck1a Posted December 8, 2022 Posted December 8, 2022 (edited) 11 hours ago, Kenneth said: A Solution I found was --Doesn't work on private java fields local indexOfField = 21 --CanHearAll local player = getPlayer() local field = getClassField(player,indexOfField) local value = getClassFieldVal(player, field) print(value) To get the index of field 0 then count in the java class files until you reach your field I wrote a function that does this for you and get field local function getField(class, fieldName) local i = 0 while true do local field = getClassField(class,i) if field:getName() == fieldName then return getClassFieldVal(class,field) end i = i + 1 end end print(getField(getPlayer(), "closestZombie")) The code could quickly become inoperable with updates. At least that hardcoded value of 21. I took a quick look at the Java classes, maybe one of this methods might solve your problem as well ---@public ---@param player int ---@return IsoZombie function IsoCell:getNearestVisibleZombie(player) end ---@public ---@return ArrayList function IsoCell:getZombieList() end Edited December 8, 2022 by stuck1a
Kenneth Posted December 9, 2022 Author Posted December 9, 2022 Hey @stuck1a thanks for the reply I think it would be best to use the methods if you find the method like you showed. But where I got stuck was at IsoChunk.vehicles I was unable to find a method to get me the vehicles in an iso chunk.
stuck1a Posted December 9, 2022 Posted December 9, 2022 (edited) 3 hours ago, Kenneth said: Hey @stuck1a thanks for the reply I think it would be best to use the methods if you find the method like you showed. But where I got stuck was at IsoChunk.vehicles I was unable to find a method to get me the vehicles in an iso chunk. Since I'm at office, I can't use my IDE to search for exposed methods, but regarding to the online docs, IsoCell provide you with that one at least: public ArrayList<BaseVehicle> getVehicles() Which means you have to calc the distance youself for each entry and find the nearest vehicle. I think luautils contains a method which will do that for you, otherwise you might calculate it yourself by using pythagorean theorem a²+b²=c² or in this context: distance = sqrt( (x_vehicle - x_plr)² + (y_vehicle - y_plr)² ) // Honestly, your solution will be faster since in this one, you have to do calculations on lua level which have already been done in Java. It therefore depends entirely on the context whether you give priority to performance or if you prefer to check with each update whether the code still works or not and correct it if necessary. Edited December 9, 2022 by stuck1a added note
Kenneth Posted December 9, 2022 Author Posted December 9, 2022 20 minutes ago, stuck1a said: Since I'm at office, I can't use my IDE to search for exposed methods, but regarding to the online docs, IsoCell provide you with that one at least: public ArrayList<BaseVehicle> getVehicles() Which means you have to calc the distance youself for each entry and find the nearest vehicle. I think luautils contains a method which will do that for you, otherwise you might calculate it yourself by using pythagorean theorem a²+b²=c² or in this context: distance = sqrt( (x_vehicle - x_plr)² + (y_vehicle - y_plr)² ) // Honestly, your solution will be faster since in this one, you have to do calculations on lua level which have already been done in Java. It therefore depends entirely on the context whether you give priority to performance or if you prefer to check with each update whether the code still works or not and correct it if necessary. So I have thought that the reason I don't want to use that because if you are close to the edge of a cell won't it disregard vehicles in adjacent cells. What I currently am doing is getting IsoChunk around player and then get vehicles from those chunks.
stuck1a Posted December 9, 2022 Posted December 9, 2022 (edited) 3 hours ago, Kenneth said: So I have thought that the reason I don't want to use that because if you are close to the edge of a cell won't it disregard vehicles in adjacent cells. What I currently am doing is getting IsoChunk around player and then get vehicles from those chunks. I was afraid that would be a problem (since I couldn't imagine sth where only the cell matters). Does that mean you need a solution that returns the nearest IsoObject of type XY, regardless of cells/chunks?. Depending on the maximum distance you want to check, the following solutions would spontaneously come to mind: - Check all squares around player position (e.g. circular with increasing radius) until you reached your maximum distance. But honestly, even if you do this as performant as possible, this is a solution I wouldn't recommend, if you have to execute this task very frequently or if your maximum radius is greater than 20-30 Squares from player position. (for r=30 squares there would be already (up to) 900 IsoSquares to check - if course only in worst case, that there isn't any target object within this radius) - Use the above functions, but check whether your search radius requires the data of one or more other cells/chunks and, if necessary, merge their object lists before iterating over them to find the nearest object. I personally would prefer method 2, if possible, since it's the one which is way more performant while staying as failsafe as possible. But if checking your mod after updates is not a problem for you, then your current solution is of course also an option. // Btw: Would you mind, if I use this nudge to implement something like FindNearestIsoObject(int x, int y, int z, bool fixZ = true, isoType = 'IsoThumpable'): IsoObject|false in my framworks util class? Since I'm pretty sure, I will require such an function as well sooner or later for my current project. Edited December 9, 2022 by stuck1a
Kenneth Posted December 9, 2022 Author Posted December 9, 2022 (edited) 5 hours ago, stuck1a said: I was afraid that would be a problem (since I couldn't imagine sth where only the cell matters). Does that mean you need a solution that returns the nearest IsoObject of type XY, regardless of cells/chunks?. Depending on the maximum distance you want to check, the following solutions would spontaneously come to mind: - Check all squares around player position (e.g. circular with increasing radius) until you reached your maximum distance. But honestly, even if you do this as performant as possible, this is a solution I wouldn't recommend, if you have to execute this task very frequently or if your maximum radius is greater than 20-30 Squares from player position. (for r=30 squares there would be already (up to) 900 IsoSquares to check - if course only in worst case, that there isn't any target object within this radius) - Use the above functions, but check whether your search radius requires the data of one or more other cells/chunks and, if necessary, merge their object lists before iterating over them to find the nearest object. I personally would prefer method 2, if possible, since it's the one which is way more performant while staying as failsafe as possible. But if checking your mod after updates is not a problem for you, then your current solution is of course also an option. // Btw: Would you mind, if I use this nudge to implement something like FindNearestIsoObject(int x, int y, int z, bool fixZ = true, isoType = 'IsoThumpable'): IsoObject|false in my framworks util class? Since I'm pretty sure, I will require such an function as well sooner or later for my current project. I can share the the code here. I get IsoChunks around the player you can just adjust the values if you want it bigger. local function getField(class, fieldName) local i = 0 while true do local field = getClassField(class,i) if field:getName() == fieldName then return getClassFieldVal(class,field) end i = i + 1 end end local function getVehiclesAroundPlayer() local currentCell = getWorld():getCell() --works local player = getPlayer() local halfSize = 20 --Increase by 10 to get more chunks local varX = player:getX() - halfSize local varY = player:getY() - halfSize local yOrigin = varY local incr = 10 local fullSize = halfSize * 2 local allVehicles = {} for _ = 0, fullSize, incr do for _ = 0, fullSize, incr do local chunk = currentCell:getChunkForGridSquare(varX, varY, 0) if not chunk then return end print(chunk) local baseVehicles = getField(chunk,"vehicles") for i = 0, baseVehicles:size()-1 do local vehicle = baseVehicles:get(i) local alreadyFound = false for _, car in ipairs(allVehicles) do if car:getId() == vehicle:getId() then alreadyFound = true break end end if alreadyFound == false then table.insert(allVehicles,vehicle) end print("vehicle Id: ",getField(vehicle,"VehicleID")) end varY = varY + incr end varY = yOrigin varX = varX + incr end return allVehicles end getVehiclesAroundPlayer() Edited December 9, 2022 by Kenneth
Kenneth Posted December 9, 2022 Author Posted December 9, 2022 (edited) @stuck1a I have another question. Can you help me with I will send link to the post. Edited December 9, 2022 by Kenneth
stuck1a Posted December 9, 2022 Posted December 9, 2022 Thanks for shared your code. Looks like a solid base to use. Quote I have another question. Can you help me with I will send link to the post. Sure, I will take a look at it
Tchernobill Posted December 16, 2022 Posted December 16, 2022 You can get the Field instances and use their methods in debug mode. You can get the Field instances but not use their methods in non-debug mode. In order to make it work out of debug mode, you can use (at your own risks) the string casts of those Field instances. If you go this road, I strongly suggest to do this parsing only once per fieldName, on first request or during init. local Verbose = true function getField(class, fieldName) local i = 0 while true do --TODO for loop with getNumClassFields(Object var0) local field = getClassField(class,i) if not field then if Verbose then print ("param "..i.." "..tostring("no field")); end return nil end --private field is not accessible out of debug mod and any access to it (even modifiers reading wil crash) --that's why I use the dirty string analysis below. local stringField = tostring(field) local isPrivate = string.sub(stringField,1,string.len("private"))=="private" local isProtected = string.sub(stringField,1,string.len("protected"))=="protected" local isRightName = fieldName == "" or stringField:sub(-#fieldName) == fieldName if not isPrivate and not isProtected then if ShoesSpeed.Verbose then print ("param "..i.." is public."); end if isRightName then return field end --if we reach here, it was not the right field (but public) else --if we reach here, it was not the right field (and private or protected) if Verbose then print ("param "..i.." is private or protected."); end end i = i + 1 end return nil end
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now