Open up the world database - Unleash the modders

    Benevolent27

    Join the Dark Side
    Joined
    Aug 21, 2015
    Messages
    585
    Reaction score
    327
    • Purchased!
    IN SHORT:
    Alright, so! This idea is for the devs to open up database access to modders. Basically have a version of StarNet that communicates with the StarMade server, performing a SQL query on a selected open database (such as the world file). There is a TON of useful information available, for which there are currently no commands, and this kind of access is a lot, LOT faster than using StarNet to run individual commands. Also the scope of what a SQL query can do is incredibly more capable than the available console commands.

    WHY THIS IS NEEDED:
    StarMade has such great potential to be modded. I know the devs want to wait for modding till they have stable codebase and all that.. But are the databases really going to change that much? And if they do, would it really be that big of a deal for scripters to update their scripts to reflect these changes? There are players that want to create really cool content for StarMade RIGHT NOW, and these players are quitting their efforts out of frustration and many of them will not be returning later. This is a missed opportunity and a loss to our community as a whole.

    Let me tell you a bit about my journey to produce some interesting content for the server I admin on (LvD).

    I'm building what I call an "event engine." This will create spontaneous instances around the universe to make it more alive and random. There may be distress calls, more unique pirate attacks, asteroid clusters, and ways to spend cash and faction points.. I spent a lot of time working on the back-end, then finished a script that that checks the star type of a system and also returns the location. This is a necessary back-bone to the whole event engine. These scripts are about as fast as I know how to make them BUT I ran into a giant problem. They aren't nearly fast enough.

    The PROBLEM:
    When testing a system for a star, I have my script load the sector and then use StarNet.jar to run a "/sector_info" command on the center of the system. It then parses the result. If no star is found, it keeps searching. If a "DOUBLE_STAR" is found, it keeps searching till two stars are found. When a "SUN" is found, it stops and returns the result (same thing with "GIANT" stars). So, the script is not doing any work it doesn't need to do. However if the system has no star, then it HAS TO continue searching till ALL possible locations return "VOID." This is a 6x6x6 grid of sectors in the center of the system (216 sectors in total). So to further reduce the time it takes, it builds a database that it then uses for future checks. It takes a split second to use the database.

    The plan here is to use the set of coordinates for the star(s) returned to determine a safe distance from them, effectively mapping out the safe sectors in a system for the event engine to use. This is important because I DON'T want to make my event engine to require players to go out to the middle of nowhere to find anything, like the old larimar asteroids. I also don't want players being lured to an unsafe sector where they burn up in a star! (Unless I do this intentionally in the scripting, of course)

    So, I did some testing on the speed of my script on different kinds of systems:
    1. Centered SUN/GIANT - ~0.5 seconds (acceptable)
    2. Double Star - 8-12 seconds (not acceptable for real-time events)
    3. Off-center SUN - 8-12 seconds (not acceptable for real-time events)
    4. Void space - 30-36 seconds (definitely NOT acceptable)
    5. Previously checked system - less than 0.1 seconds (definitely acceptable for all purposes)

    I then created a script that generated a list of all the possible systems in the main galaxy. It would then check the star type for each system, thus building up the database to make future checks lightning fast. I used a big box of the systems by basically drawing a box around the main galaxy. This returned over 40,000 possible systems! I did some rough calculations and determined that would take over 11 days of the script running continuously for it to create this database, lagging the server the whole time! In addition to this, while I was running the script, some players were having trouble connecting to the server because it was getting spammed with loading sectors and then "/sector_info" commands.

    I decided it was time to learn a little SQL and see what I could do with loading a copy of the world file as a database, doing direct queiries (since the STAR sectors do not change). Turns out there is an ENORMOUS amount of stuff I can do! It's also MUCH FASTER to query. Here's an example of a query for any star type in a 6x6x6 block of sectors (216 in total). There was no need to optimize the search or anything, I just offload all that to the database and do a brute-force check of the sectors.



    This took about a second.

    For anyone curious, I went ahead and mapped out what each "type" number meant:
    0 = SPACE_STATION
    1 = ASTEROID
    2 = PLANET
    3 = MAIN
    4 = SUN
    5 = BLACK_HOLE
    6 = VOID
    7 = LOW_ASTEROID
    8 = GIANT
    9 = DOUBLE_STAR

    So, I then created a script to run the search and I timed it.

    Look at that! Such speed, so wow!

    So then I created a loop to run the command 100 times in a screen that I detached from.. And here are the results of that:


    That is 0.67275 seconds per query. A brute force check with my script takes 30-36 seconds but here it only takes half a second! That's a GIANT DIFFERENCE. And, in addition to that, I don't need to bog the server down at all. AND I can simplify my scripting quite a bit, cutting out 90% of it. I also don't need to make any sort of duplicate database either.. This is an acceptable speed for all intents and purposes.

    So what else might the database be used for?

    Right now I've only explored the world database, which contains a plethora of information. It has info about players, entities, sectors, fleets, trade history, jumps, and fog of war. Imagine if my script had real-time access to all this information rather than an old copy of the world file.. The possibilities of what I could do with this information are nearly endless.

    So, now I wonder, what other kinds of databases does the StarMade have open in active memory? What if I could query bits of data for individual players..like that player's inventory.. or entities.. ect. There are so many things I could do with this information. And if everyone had access.. It would attract a lot of modding activity to StarMade.

    How do modders currently access information about the server and why is this not good enough?
    Right now the methodology is for the scripters to use a console command. The devs have to program this into the game code and then have it handle all the queries for relevant info. One example is "/player_info". Behind the scenes, the server does all the database queries when it is given this command and then returns the results in a format that is human readable. It includes a TON of information. IP addresses, sector location, faction stuff, ect. Then a script needs to parse all this information, throwing out what it doesn't need. Maybe the script only wants the sector location of that player. This is EXTREMELY inefficient. Allowing direct access would give scripts the capability to only poll for the information they need. And not only that, they can rely on the power of the database to return many results at once instead of having to do several individual queries, with separate instances of StarNet for every single little bit of data the script wants. <-- this is incredibly slow when doing batch processing.

    So how might this be implemented?
    From what I've read about HSQL, it is a JSQL database. Parts of it remain in memory and it does writes to the actual database on the hard drive periodically. I'm guessing this is part of what an auto-save does. So, create a StarNet.jar type tool which sends a query to the StarMade server, maybe call it "StarNetDB.jar."
    example of usage: java -jar StarNetDB.jar select:world sql: SELECT "UID", "X", "Y", "Z", "NAME", "FACTION" FROM "PUBLIC"."ENTITIES" WHERE "X" = 4 AND "Y" = 4 AND "Z" = 4;
    Result:

    (it would be a command line result, of course to be parseable by scripts, I just used my GUI console to return results easily )

    Just imagine what we could do with this. I could create a command that easily removes all pirate entities from that sector. Or maybe a "!repel" command, that moves all entities from all factions but the player's current faction out of the sector. Or maybe this is used to get a list of all entities for a faction within a system. There are all kinds of things we can do here if I had real-time access to the database. The possibilities are only limited by your imagination.

    So, what happens on the back end? Well when this command is issued by the "StarNetDB.jar", it would initiate a connection to the StarMade server and send the request along. The server then issues the SQL commands to whatever database is specified and returns the results. I'd recommend to AT FIRST make this access read-only. This would allow modders to become familiar with the database. Then later on, allow these mods to actually change values and add new values in real-time <-- This is where modding would get even MORE interesting.

    In Conclusion
    Having the ability to do SQL queries to the StarMade databases would be an incredible resource for modders. I cannot over-state the importance that modding has for a sandbox game like StarMade. We need the diversity that the community can provide. No sandbox game will survive long without modding. This is simply a fact of this kind of game.

    One of the reasons MineCraft exploded (and kept exploding) the way it did was because of server-side and client-side mods. These kept the game interesting for players for years and years and people are STILL playing it as a result. When MineCraft was being developed.. How long did it take for the devs at Mojang to release an update for MineCraft? It was a mind-numbingly slow process. Much slower than the StarMade development cycle. I remember waiting for months and months just to release horses! HORSES. And in the same time-frame, hundreds of mods were released. If everyone was stuck with vanilla minecraft.. I don't think people would have stuck around for nearly as long. But nobody cared how slow the devs were because they had all this interesting new content from modders to explore.

    I give credit to the StarMade devs for all their hard work, but they really gotta start looking at the bigger picture here. They need to determine what ways they can give power to modders to expand on their base gameplay. For every new feature the developers are capable of implementing, modders could have implemented the 20 other features if only they had the right capabilities. Opening up the database to modders would have a minimal impact on the other projects of Schine, but would give such a great amount of access to modders. I just don't see why this already isn't a thing.

    So (constructive) thoughts are welcome here. Thank you for your time!
     
    Last edited:

    DukeofRealms

    Count Duku
    Joined
    Sep 4, 2013
    Messages
    1,475
    Reaction score
    1,616
    • Schine
    Here you go, from the latest dev build :)

    Code:
    /sql_query "select ID, X, Y, Z, UID from ENTITIES"
    [CLIENT] Admin parameter 0: select ID, X, Y, Z, UID from ENTITIES
    [ADMIN COMMAND] SQL_QUERY from org.schema.schine.network.server.AdminLocalClient@2f2f537 params: [select ID, X, Y, Z, UID from ENTITIES]
    [SERVER-LOCAL-ADMIN] ---------- SQL QUERY 0 BEGIN ----------
    [SERVER-LOCAL-ADMIN] SQL#0: "ID";"X";"Y";"Z";"UID"
    [SERVER-LOCAL-ADMIN] SQL#0: "1";"2";"2";"2";"1481643293054"
    [SERVER-LOCAL-ADMIN] SQL#0: "2";"2";"2";"2";"MYSTATION"
    [SERVER-LOCAL-ADMIN] SQL#0: "3";"3";"2";"2";"NPC-HOMEBASE_3_2_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "4";"-132";"27";"-108";"NPC-HOMEBASE_-132_27_-108"
    [SERVER-LOCAL-ADMIN] SQL#0: "5";"-276";"-7";"-4";"NPC-HOMEBASE_-276_-7_-4"
    [SERVER-LOCAL-ADMIN] SQL#0: "6";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "7";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "8";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "9";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl1"
    [SERVER-LOCAL-ADMIN] SQL#0: "10";"5";"3";"3";"FLTSHP_-10000000_0_0_0_0rl10"
    [SERVER-LOCAL-ADMIN] SQL#0: "11";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl2"
    [SERVER-LOCAL-ADMIN] SQL#0: "12";"3";"2";"2";"FLTSHP_-10000000_0_0_0_0rl20"
    [SERVER-LOCAL-ADMIN] SQL#0: "13";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl3"
    [SERVER-LOCAL-ADMIN] SQL#0: "14";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl4"
    [SERVER-LOCAL-ADMIN] SQL#0: "15";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl40"
    [SERVER-LOCAL-ADMIN] SQL#0: "16";"8";"3";"8";"FLTSHP_-10000000_0_0_0_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "17";"11";"8";"14";"FLTSHP_-10000000_0_0_0_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "18";"8";"3";"8";"FLTSHP_-10000000_0_0_0_3"
    [SERVER-LOCAL-ADMIN] SQL#0: "19";"11";"11";"2";"FLTSHP_-10000000_0_0_0_4"
    [SERVER-LOCAL-ADMIN] SQL#0: "20";"5";"13";"8";"FLTSHP_-10000000_0_0_0_5"
    [SERVER-LOCAL-ADMIN] SQL#0: "21";"8";"3";"8";"FLTSHP_-10000000_0_0_0_6"
    [SERVER-LOCAL-ADMIN] SQL#0: "22";"11";"8";"14";"FLTSHP_-10000000_0_0_0_7"
    [SERVER-LOCAL-ADMIN] SQL#0: "23";"8";"3";"8";"FLTSHP_-10000000_0_0_0_8"
    [SERVER-LOCAL-ADMIN] SQL#0: "24";"11";"11";"2";"FLTSHP_-10000000_0_0_0_9"
    [SERVER-LOCAL-ADMIN] SQL#0: "25";"5";"13";"8";"FLTSHP_-10000000_0_0_0_10"
    [SERVER-LOCAL-ADMIN] SQL#0: "26";"8";"3";"8";"FLTSHP_-10000000_0_0_0_11"
    [SERVER-LOCAL-ADMIN] SQL#0: "27";"11";"8";"14";"FLTSHP_-10000000_0_0_0_12"
    [SERVER-LOCAL-ADMIN] SQL#0: "28";"8";"3";"8";"FLTSHP_-10000000_0_0_0_13"
    [SERVER-LOCAL-ADMIN] SQL#0: "29";"11";"11";"2";"FLTSHP_-10000000_0_0_0_14"
    [SERVER-LOCAL-ADMIN] SQL#0: "30";"5";"13";"8";"FLTSHP_-10000000_0_0_0_15"
    [SERVER-LOCAL-ADMIN] SQL#0: "31";"8";"3";"8";"FLTSHP_-10000000_0_0_0_16"
    [SERVER-LOCAL-ADMIN] SQL#0: "32";"11";"8";"14";"FLTSHP_-10000000_0_0_0_17"
    [SERVER-LOCAL-ADMIN] SQL#0: "33";"8";"3";"8";"FLTSHP_-10000000_0_0_0_18"
    [SERVER-LOCAL-ADMIN] SQL#0: "34";"11";"11";"2";"FLTSHP_-10000000_0_0_0_19"
    [SERVER-LOCAL-ADMIN] SQL#0: "35";"5";"13";"8";"FLTSHP_-10000000_0_0_0_20"
    [SERVER-LOCAL-ADMIN] SQL#0: "36";"8";"3";"8";"FLTSHP_-10000000_0_0_0_21"
    [SERVER-LOCAL-ADMIN] SQL#0: "37";"11";"8";"14";"FLTSHP_-10000000_0_0_0_22"
    [SERVER-LOCAL-ADMIN] SQL#0: "38";"8";"3";"8";"FLTSHP_-10000000_0_0_0_23"
    [SERVER-LOCAL-ADMIN] SQL#0: "39";"11";"11";"2";"FLTSHP_-10000000_0_0_0_24"
    [SERVER-LOCAL-ADMIN] SQL#0: "40";"5";"13";"8";"FLTSHP_-10000000_0_0_0_25"
    [SERVER-LOCAL-ADMIN] SQL#0: "41";"8";"3";"8";"FLTSHP_-10000000_0_0_0_26"
    [SERVER-LOCAL-ADMIN] SQL#0: "42";"11";"8";"14";"FLTSHP_-10000000_0_0_0_27"
    [SERVER-LOCAL-ADMIN] SQL#0: "43";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28"
    [SERVER-LOCAL-ADMIN] SQL#0: "44";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "45";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "46";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29"
    [SERVER-LOCAL-ADMIN] SQL#0: "47";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "48";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "49";"5";"13";"8";"FLTSHP_-10000000_0_0_0_30"
    [SERVER-LOCAL-ADMIN] SQL#0: "50";"5";"13";"8";"FLTSHP_-10000000_0_0_0_30rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "51";"5";"3";"3";"FLTSHP_-10000000_0_0_0_30rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "52";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31"
    [SERVER-LOCAL-ADMIN] SQL#0: "53";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "54";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "55";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32"
    [SERVER-LOCAL-ADMIN] SQL#0: "56";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "57";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "58";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33"
    [SERVER-LOCAL-ADMIN] SQL#0: "59";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "60";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "61";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34"
    [SERVER-LOCAL-ADMIN] SQL#0: "62";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "63";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "64";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35"
    [SERVER-LOCAL-ADMIN] SQL#0: "65";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "66";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "67";"8";"3";"8";"FLTSHP_-10000000_0_0_0_36"
    [SERVER-LOCAL-ADMIN] SQL#0: "68";"8";"3";"8";"FLTSHP_-10000000_0_0_0_36rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "69";"3";"2";"2";"FLTSHP_-10000000_0_0_0_36rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "70";"11";"8";"14";"FLTSHP_-10000000_0_0_0_37"
    [SERVER-LOCAL-ADMIN] SQL#0: "71";"11";"8";"14";"FLTSHP_-10000000_0_0_0_37rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "72";"3";"2";"2";"FLTSHP_-10000000_0_0_0_37rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "73";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38"
    [SERVER-LOCAL-ADMIN] SQL#0: "74";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "75";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "76";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39"
    [SERVER-LOCAL-ADMIN] SQL#0: "77";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "78";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "79";"1";"2";"1";"FLTSHP_-10000000_0_0_0_40"
    [SERVER-LOCAL-ADMIN] SQL#0: "80";"1";"3";"2";"FLTSHP_-10000000_0_0_0_41"
    [SERVER-LOCAL-ADMIN] SQL#0: "81";"1";"10";"8";"FLTSHP_-10000000_0_0_0_42"
    [SERVER-LOCAL-ADMIN] SQL#0: "82";"1";"2";"2";"FLTSHP_-10000000_0_0_0_43"
    [SERVER-LOCAL-ADMIN] SQL#0: "83";"1";"3";"2";"FLTSHP_-10000000_0_0_0_44"
    [SERVER-LOCAL-ADMIN] SQL#0: "84";"1";"10";"8";"FLTSHP_-10000000_0_0_0_45"
    [SERVER-LOCAL-ADMIN] SQL#0: "85";"1";"2";"2";"FLTSHP_-10000000_0_0_0_46"
    [SERVER-LOCAL-ADMIN] SQL#0: "86";"1";"3";"2";"FLTSHP_-10000000_0_0_0_47"
    [SERVER-LOCAL-ADMIN] SQL#0: "87";"1";"10";"8";"FLTSHP_-10000000_0_0_0_48"
    [SERVER-LOCAL-ADMIN] SQL#0: "88";"1";"2";"2";"FLTSHP_-10000000_0_0_0_49"
    [SERVER-LOCAL-ADMIN] SQL#0: "89";"4";"3";"2";"1481643637123_4_3_2_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "90";"4";"3";"3";"1481643640838_4_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "91";"4";"3";"3";"1481643640839_4_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "92";"-134";"21";"-100";"NPC-HOMEBASE_-134_21_-100"
    [SERVER-LOCAL-ADMIN] SQL#0: "93";"-276";"-12";"-13";"NPC-HOMEBASE_-276_-12_-13"
    [SERVER-LOCAL-ADMIN] SQL#0: "94";"-132";"19";"-106";"NPC-HOMEBASE_-132_19_-106"
    [SERVER-LOCAL-ADMIN] SQL#0: "95";"-278";"-13";"-7";"NPC-HOMEBASE_-278_-13_-7"
    [SERVER-LOCAL-ADMIN] SQL#0: "96";"3";"4";"3";"1481723754140_3_4_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "97";"3";"3";"3";"1481723718549_3_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "98";"3";"3";"3";"1481723718553_3_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "99";"-135";"30";"-107";"NPC-HOMEBASE_-135_30_-107"
    [SERVER-LOCAL-ADMIN] SQL#0: "100";"-283";"-9";"-11";"NPC-HOMEBASE_-283_-9_-11"
    [SERVER-LOCAL-ADMIN] SQL#0: "101";"5";"3";"3";"1481724103280_5_3_3_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "102";"5";"3";"3";"1481724103278_5_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "103";"5";"3";"3";"1481724103281_5_3_3_3"
    [SERVER-LOCAL-ADMIN] SQL#0: "104";"5";"3";"3";"1481724103279_5_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "105";"-130";"29";"-102";"NPC-HOMEBASE_-130_29_-102"
    [SERVER-LOCAL-ADMIN] SQL#0: "106";"-277";"-5";"-2";"NPC-HOMEBASE_-277_-5_-2"
    [SERVER-LOCAL-ADMIN] ---------- SQL QUERY 0 END ----------
     

    Benevolent27

    Join the Dark Side
    Joined
    Aug 21, 2015
    Messages
    585
    Reaction score
    327
    • Purchased!
    Here you go, from the latest dev build :)

    Code:
    /sql_query "select ID, X, Y, Z, UID from ENTITIES"
    [CLIENT] Admin parameter 0: select ID, X, Y, Z, UID from ENTITIES
    [ADMIN COMMAND] SQL_QUERY from org.schema.schine.network.server.AdminLocalClient@2f2f537 params: [select ID, X, Y, Z, UID from ENTITIES]
    [SERVER-LOCAL-ADMIN] ---------- SQL QUERY 0 BEGIN ----------
    [SERVER-LOCAL-ADMIN] SQL#0: "ID";"X";"Y";"Z";"UID"
    [SERVER-LOCAL-ADMIN] SQL#0: "1";"2";"2";"2";"1481643293054"
    [SERVER-LOCAL-ADMIN] SQL#0: "2";"2";"2";"2";"MYSTATION"
    [SERVER-LOCAL-ADMIN] SQL#0: "3";"3";"2";"2";"NPC-HOMEBASE_3_2_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "4";"-132";"27";"-108";"NPC-HOMEBASE_-132_27_-108"
    [SERVER-LOCAL-ADMIN] SQL#0: "5";"-276";"-7";"-4";"NPC-HOMEBASE_-276_-7_-4"
    [SERVER-LOCAL-ADMIN] SQL#0: "6";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "7";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "8";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "9";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl1"
    [SERVER-LOCAL-ADMIN] SQL#0: "10";"5";"3";"3";"FLTSHP_-10000000_0_0_0_0rl10"
    [SERVER-LOCAL-ADMIN] SQL#0: "11";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl2"
    [SERVER-LOCAL-ADMIN] SQL#0: "12";"3";"2";"2";"FLTSHP_-10000000_0_0_0_0rl20"
    [SERVER-LOCAL-ADMIN] SQL#0: "13";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl3"
    [SERVER-LOCAL-ADMIN] SQL#0: "14";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl4"
    [SERVER-LOCAL-ADMIN] SQL#0: "15";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl40"
    [SERVER-LOCAL-ADMIN] SQL#0: "16";"8";"3";"8";"FLTSHP_-10000000_0_0_0_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "17";"11";"8";"14";"FLTSHP_-10000000_0_0_0_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "18";"8";"3";"8";"FLTSHP_-10000000_0_0_0_3"
    [SERVER-LOCAL-ADMIN] SQL#0: "19";"11";"11";"2";"FLTSHP_-10000000_0_0_0_4"
    [SERVER-LOCAL-ADMIN] SQL#0: "20";"5";"13";"8";"FLTSHP_-10000000_0_0_0_5"
    [SERVER-LOCAL-ADMIN] SQL#0: "21";"8";"3";"8";"FLTSHP_-10000000_0_0_0_6"
    [SERVER-LOCAL-ADMIN] SQL#0: "22";"11";"8";"14";"FLTSHP_-10000000_0_0_0_7"
    [SERVER-LOCAL-ADMIN] SQL#0: "23";"8";"3";"8";"FLTSHP_-10000000_0_0_0_8"
    [SERVER-LOCAL-ADMIN] SQL#0: "24";"11";"11";"2";"FLTSHP_-10000000_0_0_0_9"
    [SERVER-LOCAL-ADMIN] SQL#0: "25";"5";"13";"8";"FLTSHP_-10000000_0_0_0_10"
    [SERVER-LOCAL-ADMIN] SQL#0: "26";"8";"3";"8";"FLTSHP_-10000000_0_0_0_11"
    [SERVER-LOCAL-ADMIN] SQL#0: "27";"11";"8";"14";"FLTSHP_-10000000_0_0_0_12"
    [SERVER-LOCAL-ADMIN] SQL#0: "28";"8";"3";"8";"FLTSHP_-10000000_0_0_0_13"
    [SERVER-LOCAL-ADMIN] SQL#0: "29";"11";"11";"2";"FLTSHP_-10000000_0_0_0_14"
    [SERVER-LOCAL-ADMIN] SQL#0: "30";"5";"13";"8";"FLTSHP_-10000000_0_0_0_15"
    [SERVER-LOCAL-ADMIN] SQL#0: "31";"8";"3";"8";"FLTSHP_-10000000_0_0_0_16"
    [SERVER-LOCAL-ADMIN] SQL#0: "32";"11";"8";"14";"FLTSHP_-10000000_0_0_0_17"
    [SERVER-LOCAL-ADMIN] SQL#0: "33";"8";"3";"8";"FLTSHP_-10000000_0_0_0_18"
    [SERVER-LOCAL-ADMIN] SQL#0: "34";"11";"11";"2";"FLTSHP_-10000000_0_0_0_19"
    [SERVER-LOCAL-ADMIN] SQL#0: "35";"5";"13";"8";"FLTSHP_-10000000_0_0_0_20"
    [SERVER-LOCAL-ADMIN] SQL#0: "36";"8";"3";"8";"FLTSHP_-10000000_0_0_0_21"
    [SERVER-LOCAL-ADMIN] SQL#0: "37";"11";"8";"14";"FLTSHP_-10000000_0_0_0_22"
    [SERVER-LOCAL-ADMIN] SQL#0: "38";"8";"3";"8";"FLTSHP_-10000000_0_0_0_23"
    [SERVER-LOCAL-ADMIN] SQL#0: "39";"11";"11";"2";"FLTSHP_-10000000_0_0_0_24"
    [SERVER-LOCAL-ADMIN] SQL#0: "40";"5";"13";"8";"FLTSHP_-10000000_0_0_0_25"
    [SERVER-LOCAL-ADMIN] SQL#0: "41";"8";"3";"8";"FLTSHP_-10000000_0_0_0_26"
    [SERVER-LOCAL-ADMIN] SQL#0: "42";"11";"8";"14";"FLTSHP_-10000000_0_0_0_27"
    [SERVER-LOCAL-ADMIN] SQL#0: "43";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28"
    [SERVER-LOCAL-ADMIN] SQL#0: "44";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "45";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "46";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29"
    [SERVER-LOCAL-ADMIN] SQL#0: "47";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "48";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "49";"5";"13";"8";"FLTSHP_-10000000_0_0_0_30"
    [SERVER-LOCAL-ADMIN] SQL#0: "50";"5";"13";"8";"FLTSHP_-10000000_0_0_0_30rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "51";"5";"3";"3";"FLTSHP_-10000000_0_0_0_30rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "52";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31"
    [SERVER-LOCAL-ADMIN] SQL#0: "53";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "54";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "55";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32"
    [SERVER-LOCAL-ADMIN] SQL#0: "56";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "57";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "58";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33"
    [SERVER-LOCAL-ADMIN] SQL#0: "59";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "60";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "61";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34"
    [SERVER-LOCAL-ADMIN] SQL#0: "62";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "63";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "64";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35"
    [SERVER-LOCAL-ADMIN] SQL#0: "65";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "66";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "67";"8";"3";"8";"FLTSHP_-10000000_0_0_0_36"
    [SERVER-LOCAL-ADMIN] SQL#0: "68";"8";"3";"8";"FLTSHP_-10000000_0_0_0_36rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "69";"3";"2";"2";"FLTSHP_-10000000_0_0_0_36rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "70";"11";"8";"14";"FLTSHP_-10000000_0_0_0_37"
    [SERVER-LOCAL-ADMIN] SQL#0: "71";"11";"8";"14";"FLTSHP_-10000000_0_0_0_37rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "72";"3";"2";"2";"FLTSHP_-10000000_0_0_0_37rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "73";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38"
    [SERVER-LOCAL-ADMIN] SQL#0: "74";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "75";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "76";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39"
    [SERVER-LOCAL-ADMIN] SQL#0: "77";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "78";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "79";"1";"2";"1";"FLTSHP_-10000000_0_0_0_40"
    [SERVER-LOCAL-ADMIN] SQL#0: "80";"1";"3";"2";"FLTSHP_-10000000_0_0_0_41"
    [SERVER-LOCAL-ADMIN] SQL#0: "81";"1";"10";"8";"FLTSHP_-10000000_0_0_0_42"
    [SERVER-LOCAL-ADMIN] SQL#0: "82";"1";"2";"2";"FLTSHP_-10000000_0_0_0_43"
    [SERVER-LOCAL-ADMIN] SQL#0: "83";"1";"3";"2";"FLTSHP_-10000000_0_0_0_44"
    [SERVER-LOCAL-ADMIN] SQL#0: "84";"1";"10";"8";"FLTSHP_-10000000_0_0_0_45"
    [SERVER-LOCAL-ADMIN] SQL#0: "85";"1";"2";"2";"FLTSHP_-10000000_0_0_0_46"
    [SERVER-LOCAL-ADMIN] SQL#0: "86";"1";"3";"2";"FLTSHP_-10000000_0_0_0_47"
    [SERVER-LOCAL-ADMIN] SQL#0: "87";"1";"10";"8";"FLTSHP_-10000000_0_0_0_48"
    [SERVER-LOCAL-ADMIN] SQL#0: "88";"1";"2";"2";"FLTSHP_-10000000_0_0_0_49"
    [SERVER-LOCAL-ADMIN] SQL#0: "89";"4";"3";"2";"1481643637123_4_3_2_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "90";"4";"3";"3";"1481643640838_4_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "91";"4";"3";"3";"1481643640839_4_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "92";"-134";"21";"-100";"NPC-HOMEBASE_-134_21_-100"
    [SERVER-LOCAL-ADMIN] SQL#0: "93";"-276";"-12";"-13";"NPC-HOMEBASE_-276_-12_-13"
    [SERVER-LOCAL-ADMIN] SQL#0: "94";"-132";"19";"-106";"NPC-HOMEBASE_-132_19_-106"
    [SERVER-LOCAL-ADMIN] SQL#0: "95";"-278";"-13";"-7";"NPC-HOMEBASE_-278_-13_-7"
    [SERVER-LOCAL-ADMIN] SQL#0: "96";"3";"4";"3";"1481723754140_3_4_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "97";"3";"3";"3";"1481723718549_3_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "98";"3";"3";"3";"1481723718553_3_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "99";"-135";"30";"-107";"NPC-HOMEBASE_-135_30_-107"
    [SERVER-LOCAL-ADMIN] SQL#0: "100";"-283";"-9";"-11";"NPC-HOMEBASE_-283_-9_-11"
    [SERVER-LOCAL-ADMIN] SQL#0: "101";"5";"3";"3";"1481724103280_5_3_3_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "102";"5";"3";"3";"1481724103278_5_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "103";"5";"3";"3";"1481724103281_5_3_3_3"
    [SERVER-LOCAL-ADMIN] SQL#0: "104";"5";"3";"3";"1481724103279_5_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "105";"-130";"29";"-102";"NPC-HOMEBASE_-130_29_-102"
    [SERVER-LOCAL-ADMIN] SQL#0: "106";"-277";"-5";"-2";"NPC-HOMEBASE_-277_-5_-2"
    [SERVER-LOCAL-ADMIN] ---------- SQL QUERY 0 END ----------
    Oh my holy goodness. Is this real? Oh my gosh oh my gosh. I need to test this out immediately! Thank you thank you thank you!
     
    Last edited:

    Benevolent27

    Join the Dark Side
    Joined
    Aug 21, 2015
    Messages
    585
    Reaction score
    327
    • Purchased!
    Here you go, from the latest dev build :)

    Code:
    /sql_query "select ID, X, Y, Z, UID from ENTITIES"
    [CLIENT] Admin parameter 0: select ID, X, Y, Z, UID from ENTITIES
    [ADMIN COMMAND] SQL_QUERY from org.schema.schine.network.server.AdminLocalClient@2f2f537 params: [select ID, X, Y, Z, UID from ENTITIES]
    [SERVER-LOCAL-ADMIN] ---------- SQL QUERY 0 BEGIN ----------
    [SERVER-LOCAL-ADMIN] SQL#0: "ID";"X";"Y";"Z";"UID"
    [SERVER-LOCAL-ADMIN] SQL#0: "1";"2";"2";"2";"1481643293054"
    [SERVER-LOCAL-ADMIN] SQL#0: "2";"2";"2";"2";"MYSTATION"
    [SERVER-LOCAL-ADMIN] SQL#0: "3";"3";"2";"2";"NPC-HOMEBASE_3_2_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "4";"-132";"27";"-108";"NPC-HOMEBASE_-132_27_-108"
    [SERVER-LOCAL-ADMIN] SQL#0: "5";"-276";"-7";"-4";"NPC-HOMEBASE_-276_-7_-4"
    [SERVER-LOCAL-ADMIN] SQL#0: "6";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "7";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "8";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "9";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl1"
    [SERVER-LOCAL-ADMIN] SQL#0: "10";"5";"3";"3";"FLTSHP_-10000000_0_0_0_0rl10"
    [SERVER-LOCAL-ADMIN] SQL#0: "11";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl2"
    [SERVER-LOCAL-ADMIN] SQL#0: "12";"3";"2";"2";"FLTSHP_-10000000_0_0_0_0rl20"
    [SERVER-LOCAL-ADMIN] SQL#0: "13";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl3"
    [SERVER-LOCAL-ADMIN] SQL#0: "14";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl4"
    [SERVER-LOCAL-ADMIN] SQL#0: "15";"5";"13";"8";"FLTSHP_-10000000_0_0_0_0rl40"
    [SERVER-LOCAL-ADMIN] SQL#0: "16";"8";"3";"8";"FLTSHP_-10000000_0_0_0_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "17";"11";"8";"14";"FLTSHP_-10000000_0_0_0_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "18";"8";"3";"8";"FLTSHP_-10000000_0_0_0_3"
    [SERVER-LOCAL-ADMIN] SQL#0: "19";"11";"11";"2";"FLTSHP_-10000000_0_0_0_4"
    [SERVER-LOCAL-ADMIN] SQL#0: "20";"5";"13";"8";"FLTSHP_-10000000_0_0_0_5"
    [SERVER-LOCAL-ADMIN] SQL#0: "21";"8";"3";"8";"FLTSHP_-10000000_0_0_0_6"
    [SERVER-LOCAL-ADMIN] SQL#0: "22";"11";"8";"14";"FLTSHP_-10000000_0_0_0_7"
    [SERVER-LOCAL-ADMIN] SQL#0: "23";"8";"3";"8";"FLTSHP_-10000000_0_0_0_8"
    [SERVER-LOCAL-ADMIN] SQL#0: "24";"11";"11";"2";"FLTSHP_-10000000_0_0_0_9"
    [SERVER-LOCAL-ADMIN] SQL#0: "25";"5";"13";"8";"FLTSHP_-10000000_0_0_0_10"
    [SERVER-LOCAL-ADMIN] SQL#0: "26";"8";"3";"8";"FLTSHP_-10000000_0_0_0_11"
    [SERVER-LOCAL-ADMIN] SQL#0: "27";"11";"8";"14";"FLTSHP_-10000000_0_0_0_12"
    [SERVER-LOCAL-ADMIN] SQL#0: "28";"8";"3";"8";"FLTSHP_-10000000_0_0_0_13"
    [SERVER-LOCAL-ADMIN] SQL#0: "29";"11";"11";"2";"FLTSHP_-10000000_0_0_0_14"
    [SERVER-LOCAL-ADMIN] SQL#0: "30";"5";"13";"8";"FLTSHP_-10000000_0_0_0_15"
    [SERVER-LOCAL-ADMIN] SQL#0: "31";"8";"3";"8";"FLTSHP_-10000000_0_0_0_16"
    [SERVER-LOCAL-ADMIN] SQL#0: "32";"11";"8";"14";"FLTSHP_-10000000_0_0_0_17"
    [SERVER-LOCAL-ADMIN] SQL#0: "33";"8";"3";"8";"FLTSHP_-10000000_0_0_0_18"
    [SERVER-LOCAL-ADMIN] SQL#0: "34";"11";"11";"2";"FLTSHP_-10000000_0_0_0_19"
    [SERVER-LOCAL-ADMIN] SQL#0: "35";"5";"13";"8";"FLTSHP_-10000000_0_0_0_20"
    [SERVER-LOCAL-ADMIN] SQL#0: "36";"8";"3";"8";"FLTSHP_-10000000_0_0_0_21"
    [SERVER-LOCAL-ADMIN] SQL#0: "37";"11";"8";"14";"FLTSHP_-10000000_0_0_0_22"
    [SERVER-LOCAL-ADMIN] SQL#0: "38";"8";"3";"8";"FLTSHP_-10000000_0_0_0_23"
    [SERVER-LOCAL-ADMIN] SQL#0: "39";"11";"11";"2";"FLTSHP_-10000000_0_0_0_24"
    [SERVER-LOCAL-ADMIN] SQL#0: "40";"5";"13";"8";"FLTSHP_-10000000_0_0_0_25"
    [SERVER-LOCAL-ADMIN] SQL#0: "41";"8";"3";"8";"FLTSHP_-10000000_0_0_0_26"
    [SERVER-LOCAL-ADMIN] SQL#0: "42";"11";"8";"14";"FLTSHP_-10000000_0_0_0_27"
    [SERVER-LOCAL-ADMIN] SQL#0: "43";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28"
    [SERVER-LOCAL-ADMIN] SQL#0: "44";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "45";"8";"3";"8";"FLTSHP_-10000000_0_0_0_28rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "46";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29"
    [SERVER-LOCAL-ADMIN] SQL#0: "47";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "48";"11";"11";"2";"FLTSHP_-10000000_0_0_0_29rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "49";"5";"13";"8";"FLTSHP_-10000000_0_0_0_30"
    [SERVER-LOCAL-ADMIN] SQL#0: "50";"5";"13";"8";"FLTSHP_-10000000_0_0_0_30rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "51";"5";"3";"3";"FLTSHP_-10000000_0_0_0_30rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "52";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31"
    [SERVER-LOCAL-ADMIN] SQL#0: "53";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "54";"8";"3";"8";"FLTSHP_-10000000_0_0_0_31rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "55";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32"
    [SERVER-LOCAL-ADMIN] SQL#0: "56";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "57";"11";"8";"14";"FLTSHP_-10000000_0_0_0_32rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "58";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33"
    [SERVER-LOCAL-ADMIN] SQL#0: "59";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "60";"8";"3";"8";"FLTSHP_-10000000_0_0_0_33rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "61";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34"
    [SERVER-LOCAL-ADMIN] SQL#0: "62";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "63";"11";"11";"2";"FLTSHP_-10000000_0_0_0_34rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "64";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35"
    [SERVER-LOCAL-ADMIN] SQL#0: "65";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "66";"5";"13";"8";"FLTSHP_-10000000_0_0_0_35rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "67";"8";"3";"8";"FLTSHP_-10000000_0_0_0_36"
    [SERVER-LOCAL-ADMIN] SQL#0: "68";"8";"3";"8";"FLTSHP_-10000000_0_0_0_36rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "69";"3";"2";"2";"FLTSHP_-10000000_0_0_0_36rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "70";"11";"8";"14";"FLTSHP_-10000000_0_0_0_37"
    [SERVER-LOCAL-ADMIN] SQL#0: "71";"11";"8";"14";"FLTSHP_-10000000_0_0_0_37rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "72";"3";"2";"2";"FLTSHP_-10000000_0_0_0_37rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "73";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38"
    [SERVER-LOCAL-ADMIN] SQL#0: "74";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "75";"8";"3";"8";"FLTSHP_-10000000_0_0_0_38rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "76";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39"
    [SERVER-LOCAL-ADMIN] SQL#0: "77";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39rl0"
    [SERVER-LOCAL-ADMIN] SQL#0: "78";"11";"11";"2";"FLTSHP_-10000000_0_0_0_39rl00"
    [SERVER-LOCAL-ADMIN] SQL#0: "79";"1";"2";"1";"FLTSHP_-10000000_0_0_0_40"
    [SERVER-LOCAL-ADMIN] SQL#0: "80";"1";"3";"2";"FLTSHP_-10000000_0_0_0_41"
    [SERVER-LOCAL-ADMIN] SQL#0: "81";"1";"10";"8";"FLTSHP_-10000000_0_0_0_42"
    [SERVER-LOCAL-ADMIN] SQL#0: "82";"1";"2";"2";"FLTSHP_-10000000_0_0_0_43"
    [SERVER-LOCAL-ADMIN] SQL#0: "83";"1";"3";"2";"FLTSHP_-10000000_0_0_0_44"
    [SERVER-LOCAL-ADMIN] SQL#0: "84";"1";"10";"8";"FLTSHP_-10000000_0_0_0_45"
    [SERVER-LOCAL-ADMIN] SQL#0: "85";"1";"2";"2";"FLTSHP_-10000000_0_0_0_46"
    [SERVER-LOCAL-ADMIN] SQL#0: "86";"1";"3";"2";"FLTSHP_-10000000_0_0_0_47"
    [SERVER-LOCAL-ADMIN] SQL#0: "87";"1";"10";"8";"FLTSHP_-10000000_0_0_0_48"
    [SERVER-LOCAL-ADMIN] SQL#0: "88";"1";"2";"2";"FLTSHP_-10000000_0_0_0_49"
    [SERVER-LOCAL-ADMIN] SQL#0: "89";"4";"3";"2";"1481643637123_4_3_2_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "90";"4";"3";"3";"1481643640838_4_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "91";"4";"3";"3";"1481643640839_4_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "92";"-134";"21";"-100";"NPC-HOMEBASE_-134_21_-100"
    [SERVER-LOCAL-ADMIN] SQL#0: "93";"-276";"-12";"-13";"NPC-HOMEBASE_-276_-12_-13"
    [SERVER-LOCAL-ADMIN] SQL#0: "94";"-132";"19";"-106";"NPC-HOMEBASE_-132_19_-106"
    [SERVER-LOCAL-ADMIN] SQL#0: "95";"-278";"-13";"-7";"NPC-HOMEBASE_-278_-13_-7"
    [SERVER-LOCAL-ADMIN] SQL#0: "96";"3";"4";"3";"1481723754140_3_4_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "97";"3";"3";"3";"1481723718549_3_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "98";"3";"3";"3";"1481723718553_3_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "99";"-135";"30";"-107";"NPC-HOMEBASE_-135_30_-107"
    [SERVER-LOCAL-ADMIN] SQL#0: "100";"-283";"-9";"-11";"NPC-HOMEBASE_-283_-9_-11"
    [SERVER-LOCAL-ADMIN] SQL#0: "101";"5";"3";"3";"1481724103280_5_3_3_2"
    [SERVER-LOCAL-ADMIN] SQL#0: "102";"5";"3";"3";"1481724103278_5_3_3_0"
    [SERVER-LOCAL-ADMIN] SQL#0: "103";"5";"3";"3";"1481724103281_5_3_3_3"
    [SERVER-LOCAL-ADMIN] SQL#0: "104";"5";"3";"3";"1481724103279_5_3_3_1"
    [SERVER-LOCAL-ADMIN] SQL#0: "105";"-130";"29";"-102";"NPC-HOMEBASE_-130_29_-102"
    [SERVER-LOCAL-ADMIN] SQL#0: "106";"-277";"-5";"-2";"NPC-HOMEBASE_-277_-5_-2"
    [SERVER-LOCAL-ADMIN] ---------- SQL QUERY 0 END ----------
    YES! I HAD A SUCCESSFUL RUN FOR A COMMAND TO CHECK ALL STARS IN A SYSTEM!


    (the command run is in the text box)

    Though I did run into a few issues unfortunately! At first, it wasn't working, so I tried loading the sectors via the "/load_sector_range 5 5 5 10 10 10" command. That didn't work. No results. So I tried manually to scanning the system in game. THEN it worked! So it seems that fog of war was hiding the results from me! Oh boy! So, there needs to be a way to do queries on systems that are hidden by fog of war. Any ideas?

    But, now to add to this idea to make it more accessible to modders and server-operators, the next step here is to create aliases. These would be pre-formated commands in a config file, such as "aliases.cfg". At first, this could be relatively simple and then extra functionality added later, such as formatting the output. I'm not entirely sure how to best format this config file, but I have done scripting for bots and such that had exactly this kind of functionality, so it's definitely possible. I'll update this post after I have some time to do more research on better formatting. (The dev's of course might have an idea of how they would prefer it to be formatted too, of course)

    Example aliases.cfg file:
    Code:
    # This configuration file is used to create aliases which become usable commands in game.
    # All characters that are placed after a "#" character will not be processed by the game engine, so feel free to place comments wherever you would like in this file.
    # Variables can be used, such as $1 and $2 to capture input from the user.
    # Note that when declaring an alias, any character can be used, but a "/" character is needed to make this a command run by users without being visible to other players.  If any other symbol is used or no symbol is used, then the command will also be visible as a chat message in whichever chat box the user typed the command into.  The command output will also display to all users in that chat room.
    ALIAS /check_system_star_type {
    [permissions]
    # When setting permissions, there are four options available, "//allow_group", "//allow_player", "//disallow_group", and "//disallow_player".  
    # By default, if a group or player is not given permission to use this alias command, they will be given an error explaining that they do not have permission to use it.  Further expansion on permission structures are planned for a future update.
    //allow_group admins
    //allow_group console
    [/permissions]
    
    [run_command]
    # "//send_console_command" is used here to send a console command because this will future-proof additional compatibility with scripting functionality.  For example, if/then/else .
    //send_console_command /sql_query "SELECT X, Y, Z, TYPE FROM PUBLIC.SECTORS WHERE X BETWEEN $1 AND $4 AND Y BETWEEN $2 AND $5 AND Z BETWEEN $3 AND $6 AND (TYPE = 4 OR TYPE BETWEEN 8 AND 9);"
    [/run_command]
    
    [help]
    //output This command runs a SQL query of a range of sectors, returning only star types and their coordinates.
    //output Usage: /check_system_star_type fromX(Integer) fromY(Integer) fromZ(Integer) toX(integer) toY(integer) toZ(Integer) (e.g.: /check_system_star_type 5 5 5 10 10 10
    [/help]
    }
    Examples of usage in game or when used from the command console:

    An admin types the following command in-game or in the command console and presses enter:
    Code:
    /check_system_star_type
    Result:
    Code:
    GENERAL: [ERROR] This command runs a SQL query of a range of sectors, returning only star types and their coordinates.
    GENERAL: [ERROR] Usage: /check_system_star_type fromX(Integer) fromY(Integer) fromZ(Integer) toX(integer) toY(integer) toZ(Integer) (e.g.: /check_system_star_type 5 5 5 10 10 10
    A player types the following command in-game and presses enter:
    Code:
    GENERAL: [ERROR] Sorry, only admins have access to this command and you are not an admin!
    An admin types the following command in-game or in the command console and presses enter:
    /check_system_star_type 5 5 5 10 10 10
    Result:
    Code:
    [SERVER]: ---------- SQL QUERY 0 BEGIN ----------
    [SERVER]: SQL#0: "X";"Y";"Z";"TYPE"
    [SERVER]: SQL#0: "8";"8";"8";"4"
    [SERVER]: ---------- SQL QUERY 0 END ----------
    Now, later on, giving the ability to somehow format the output would be ideal. Perhaps the best way to do this is to simply call on an outside script to do this, basically feeding all of the output text to that script (yes I am aware that this can be potentially dangerous but it is no different from what current wrappers do to process text - there may want to be some consideration given to potential command injection). Whatever is returned by the script is then returned to the player as text. There could also be an option to run an outside script using the input of the user. (Example: //run_script ./scripts/help.sh $*) This would essentially make it so every server has a front-end for a simple command driven wrapper. For example, server admins might set up a "!rules" alias, which returns the rules of the server. No need for installation of a custom wrapper at all!

    As always, thoughts and suggestions are welcome!
     
    Last edited:
    Joined
    Dec 16, 2013
    Messages
    130
    Reaction score
    83
    • Legacy Citizen 2
    • Community Content - Bronze 1
    • Purchased!
    • Legacy Citizen
    Very interesting indeed,
    I'll need to play with this, and the new update. So many times to check out!

    It would be nice to have starmade at least offer a way we can send commands to where a wrapper can read them, but other players on the server cannot (commands like !rules). Right now players can do this manually by typing in a seperate chat, but it would be nice to have an option to have say everything that starts with a ! not be displayed to other players.

    Yeah, injection could be an issue here. However, I'll be adding this to the primary lib in stard and see what I can do to avoid it. However, such injection would only risk getting corrupted/incorrect data.

    Thanks Duke!
     
    Last edited:

    Benevolent27

    Join the Dark Side
    Joined
    Aug 21, 2015
    Messages
    585
    Reaction score
    327
    • Purchased!
    Very interesting indeed,
    I'll need to play with this, and the new update. So many times to check out!

    It would be nice to have starmade at least offer a way we can send commands to where a wrapper can read them, but other players on the server cannot (commands like !rules). Right now players can do this manually by typing in a seperate chat, but it would be nice to have an option to have say everything that starts with a ! not be displayed to other players.

    Yeah, injection could be an issue here. However, I'll be adding this to the primary lib in stard and see what I can do to avoid it. However, such injection would only risk getting corrupted/incorrect data.

    Thanks Duke!
    This could be possible with aliases, if they allowed wildcards and could run a script, using the text a player typed.

    What do you think about the idea for aliases?
     
    Joined
    Dec 16, 2013
    Messages
    130
    Reaction score
    83
    • Legacy Citizen 2
    • Community Content - Bronze 1
    • Purchased!
    • Legacy Citizen
    Howdy,
    I'm not certain I get it. As I understand it, the thought is to create a commands of different names that would perform other commands that may be already filled out, similar to how aliases work (like in bash where you alias commands like ls -l to be aliasable as ll).

    For modding, I don't see the use, as one would need to replicate the aliases on one server to another to make their scripts work correctly.

    For allowing user to run command that would normally be admin commands, perhaps could be useful.

    For admins, it could provide a nifty shortcut, maybe helpful for debugging purposes with the sql_query.

    The main helpful feature I see would be the ability to supress chat messages of the commands. Though this could be provided with significantly less effort. Say a config file option for messages to supress (ie CHAT_SEPRESS_PREFIX=! to supress any messages that start with a !)

    Edit: Allowing the ability to call outside scripts could be useful, as you said for providing the ability call and execute scripts, like some existing wrappers can, would be helpful. I likely wouldn't use it myself, as I have a working solution already, but that doesn't mean others won't. I don't know, the question is, is it worth it to build it into starmade when solutions already exist outside of starmade.
     
    Last edited:
    • Like
    Reactions: timmymorrison1
    Joined
    Aug 28, 2013
    Messages
    26
    Reaction score
    1
    • Legacy Citizen 4
    This would be too nice, modding is a gateway, it opens the game to new possibilities. so many player will play on servers with od than the actual game.
    [doublepost=1493867520,1493867357][/doublepost]Its almost needed at this point. the player base is thinning out, alot of people have left. modding would be pretty much the thing that might make starmade the best game around.
     

    DukeofRealms

    Count Duku
    Joined
    Sep 4, 2013
    Messages
    1,475
    Reaction score
    1,616
    • Schine
    This would be too nice, modding is a gateway, it opens the game to new possibilities. so many player will play on servers with od than the actual game.
    [doublepost=1493867520,1493867357][/doublepost]Its almost needed at this point. the player base is thinning out, alot of people have left. modding would be pretty much the thing that might make starmade the best game around.

    We've always said modding will be a significant part of StarMade, eventually. Implementing a mod API right now, simply in the hopes to "save dead game" (which, as I've said numerous times, is simply not true) would be foolish.

    Eventually, we will have a modding api, it will be in when we are ready for it.
     

    Lone_Puppy

    Me, myself and I.
    Joined
    Mar 12, 2015
    Messages
    1,274
    Reaction score
    529
    • Purchased!
    • Community Content - Bronze 2
    • Legacy Citizen 8
    Wow, you could build an awesome debug tool with this approach. Not to mention a server admins paradise. :)
     
    Joined
    Aug 28, 2013
    Messages
    26
    Reaction score
    1
    • Legacy Citizen 4
    [10:27 PM] DestroyerOfWorlds: I still think they shouldn't change the power system at all, but rather give more options for variability
    [10:28 PM] DestroyerOfWorlds: Allow the modding community to come up with different options, and then let players test the various systems through gameplay, and see which ones are the most popular
    [10:28 PM] DestroyerOfWorlds: Then set up a few different default config options based on those
    [10:29 PM] DestroyerOfWorlds: But retain the modding capabilities for servers that want different forms of power
    [10:36 PM] DestroyerOfWorlds: I say, add the capability for multi-block sub-entities, such as power reactors
    [10:37 PM] DestroyerOfWorlds: So you could have various different kinds of reactors, that behave a bit differently and have different requirements for power.
    [10:39 PM] DestroyerOfWorlds: Like, planets might have small amounts of uranium. These materials can then be processed into a refined uranium and put into a nuclear reactor, which would produce a lot of power, but would need to have cooling systems, and if it overheats due to lack of cooling (or is damaged in combat), it blows up spectacularly
    [10:39 PM] DestroyerOfWorlds: Could also have biofuel type reactors, which are a lot more stable, but produce less power. However, they would require biofuel to be created from plant matter
    [10:40 PM] DestroyerOfWorlds: So, this would require additional types of factories to be creatable and for recipes to be remembered upon server updates rather than lost, as they are now.
    [10:41 PM] DestroyerOfWorlds: Could also be solar panels, which produce smaller amounts of power and are dependent on being closer to a star to produce meaningful amounts of power
    [10:41 PM] DestroyerOfWorlds: There are a lot of possibilities, but until they put in the mechanics for these sorts of systems to exist, they will not exist.
    [10:50 PM] DestroyerOfWorlds: Sure, there could be jump drives of different qualities too
    [10:52 PM] DestroyerOfWorlds: make a multi-block entity that has the properties of being equippable on the weapons menu, have the left-click function be to jump 8 sectors, but require 1 "phase-matter" (or whatever you want to call it). It would have it's own internal storage and could be linked to a storage to pull from, like a shipyard
    [10:53 PM] DestroyerOfWorlds: And give it a cool time that is dependent on the amount of cooling it has
    [10:53 PM] DestroyerOfWorlds: So, you'd attach heat-sinks or other types of cooling. Perhaps there could be fans running on heat sinks for standard cooling. Or have phase induction type cooling, which takes more power but is more effective.
    [10:54 PM] DestroyerOfWorlds: (These are the types of mods I'd produce if I had the capability)
    [doublepost=1493872090,1493871961][/doublepost]eh with that alone is enough to bring me back in the game. lol
    [doublepost=1493872193][/doublepost]as a use-to be player of sm
     
    • Like
    Reactions: Benevolent27

    Benevolent27

    Join the Dark Side
    Joined
    Aug 21, 2015
    Messages
    585
    Reaction score
    327
    • Purchased!
    Howdy,
    I'm not certain I get it. As I understand it, the thought is to create a commands of different names that would perform other commands that may be already filled out, similar to how aliases work (like in bash where you alias commands like ls -l to be aliasable as ll).

    For modding, I don't see the use, as one would need to replicate the aliases on one server to another to make their scripts work correctly.

    For allowing user to run command that would normally be admin commands, perhaps could be useful.

    For admins, it could provide a nifty shortcut, maybe helpful for debugging purposes with the sql_query.

    The main helpful feature I see would be the ability to supress chat messages of the commands. Though this could be provided with significantly less effort. Say a config file option for messages to supress (ie CHAT_SEPRESS_PREFIX=! to supress any messages that start with a !)

    Edit: Allowing the ability to call outside scripts could be useful, as you said for providing the ability call and execute scripts, like some existing wrappers can, would be helpful. I likely wouldn't use it myself, as I have a working solution already, but that doesn't mean others won't. I don't know, the question is, is it worth it to build it into starmade when solutions already exist outside of starmade.
    "Aliases" is just what you would call it to separate it from something like "functions". An alias is a simpler translation that doesn't process the input, but rather passes information to another command. It does NOT have to work exactly how bash aliases work, which is a merely a word replacement. An alias is how you create the custom command and then have it do something, passing input to the "something". The alias may run a more complicated in-game command or it may call a function or outside script which would then process the input, and the return text would be sent back to the player.

    In the example I gave in one of my above responses, I take a complicated SQL query command that checks for stars within sector coordinates,
    Code:
    /sql_query "SELECT X, Y, Z TYPE FROM PUBLIC.SECTORS WHERE X BETWEEN 5 AND 10 AND Y BETWEEN 5 AND 10 AND Z BETWEEN 5 AND 10 AND (TYPE = 4 OR TYPE BETWEEN 8 AND 9);"
    and I use an alias to have the following command run the longer command:
    Code:
    /check_system_star_type 5 5 5 10 10 10
    Both do the exact same thing and have the same output, but one is a lot easier to type, and becomes practical to use. Other commands could then be created to do other SQL queries, such as list all the recent deaths, or logins, or whatever other information is included in the world database.
    Here is what the ouput would look like:
    Code:
    [SERVER]: ---------- SQL QUERY 0 BEGIN ----------
    [SERVER]: SQL#0: "X";"Y";"Z";"TYPE"
    [SERVER]: SQL#0: "8";"8";"8";"4"
    [SERVER]: ---------- SQL QUERY 0 END ----------
    The next logical step would be to then have "functions", which can actually process the input information AND process the text that is returned. These could have if/then/else/elseif capabilities. It could then return text back to the user in a different manner. So, for example, let's say we have an alias call a function instead of run a straight up command. So, from the above example, the output looks like:
    Code:
    [SERVER]: ---------- SQL QUERY 0 BEGIN ----------
    [SERVER]: SQL#0: "X";"Y";"Z";"TYPE"
    [SERVER]: SQL#0: "8";"8";"8";"4"
    [SERVER]: ---------- SQL QUERY 0 END ----------
    If you know what you are looking at, then you know that at sector coordinates "8 8 8" there is a type 4 star, which is a normal type star. However, a function might parse the text and return instead the text:
    Code:
    [SERVER]: A regular star was found at coordinates 8,8,8.
    Or if no star was found, perhaps:
    Code:
    [SERVER]: No star was found within the coordinate range of 5 5 5 and 10 10 10.
    I suggest this sort of terminology (aliases and functions) because I used to script for a bot a long time ago that had a similar sort of setup, and it made it quite easy to do both quick and easy commands (with a simple alias) or have more robust commands with extended processing (with a function).

    [doublepost=1494883142,1494881396][/doublepost]
    We've always said modding will be a significant part of StarMade, eventually. Implementing a mod API right now, simply in the hopes to "save dead game" (which, as I've said numerous times, is simply not true) would be foolish.

    Eventually, we will have a modding api, it will be in when we are ready for it.
    Edit: I feel I should say here that there already IS a sort of modding API, in that the console output (or logs) can be parsed, and then StarNet.jar and the commands available can be used to control certain aspects of the game and also parse the return of each command.

    I don't think modding should be implemented to "save dead game," nor would I call StarMade a dead game. I just think that flexibility in the game engine makes sense to be the backbone of a sandbox game. Create the backbone functions first, and then devs use those to implement new features. For example, there already is a framework for blocks. The blocks are populated from a list, given textures, and then have different properties assigned to them (such as whether they are placable or not, animated, ect). The game does not have each block hard-coded into the game code and I think it would be hard to argue that they should be. When a new block is to be introduced into the game, all the devs have to do is add a new block ID, new texture, and assign properties to it. They do not need to hard-code some new block into the game code. In the same way, if we apply the same principal to other features of the game, creating the groundwork for the feature and then the feature, it allows a stable platform for variability in the game engine and the same backbone features are usable by other new features. This would make it easier for the game developers to balance features, create new ones, and also would make it easier for players to create novel features using the same backbone capabilities.

    But would this sort of strategy allow more variability in the game and make it more interesting? Sure. Do I think this would bring new players to StarMade and help keep old ones? Yep. Would that be a bad thing? I don't believe so.

    I also don't think this would restrict the game any more than the current development strategy does. As long as the back-bone functions retain their functions. For example, let's say a command "/resource_info X Y Z" returns a number that quantifies the estimated resource count of an entire system and the feature is used by the NPC factions. If the code behind the scenes changes, the formatting for output could still be the same even if the number changes (or how that number is arrived at changes). So this sort of change wouldn't break the internal systems or "mods" that rely on the command to function. We already have some modding capability with the existing commands by parsing the output. Do the dev's feel constricted because a "/player_info" command exists? Does the presence of the admin commands listed here impede the dev's? A good way to know would be to see whether the dev's complained at all, saying something like.. "If only we didn't have a /spawn_entity_pos command implemented.. How are we going to implement NPC factions now that players are using that command?" Would it be better to remove the admin commands? If not, then consider my point here. :)
     
    Last edited:
    • Like
    Reactions: Lone_Puppy