Skip to content

Releases: PraxisMapper/PraxisMapper

Release 12

12 May 01:53
Compare
Choose a tag to compare

The focus for Release 12 has been offline data and Godot support via PraxisGodotComponents. Part of the unusual lull between releases has been the focus on the client-side of things, and partly because of the time it took to process global data into offline form for testing and development of that. But its in a pretty stable spot, so now's a good time to release the changes.

Server/Core:

  • arts&culture style has been expanded to 18 different entries, 1 for each of the elements that was in the original. This will help descriptiveness of games that use them dramatically, by saying you're at a library or a viewpoint instead of "arts&culture place". Applied to mapTiles, suggestedGameplay, and suggestedmini style.
  • Offline data formats changes. Its still JSON, but in 2 different schemas now, depending on if its 'minimized' or 'drawable'. Larry can make these for a server with with -makeOfflineFiles or -makeMinimizedFiles. The Offline plugin can generate them on-demand at /Offline/V2/{plusCode}/{styles} or /Offline/V2Min/{plusCode}/{styles}
    • Each JSON file will have the 6-digit OpenLocationCode, a nametable holding unique Place names, and a list of entries
    • For full drawable offline data, entries is a dictionary, with a key of the styleSet used to make the data, and a list of data points each containing nid (Name table ID), tid (type ID, the matchOrder value in the style set used), gt (Geometry type, to indicate if its a Point/Line/Polygon), and p (Points, local-coordinate positions in pixel values. Default settings use Cell12s as pixels, which makes this coordinate grid 6,400x10,000)
    • For minimized estimated offline data, the entries contain a nid (Name table ID), tid (type ID, the matchOrder value in the style set used), c (Center of the circle, as a local-coordinate pixel position), and r (radius of the circle, in local coordinate pixels). These files use Cell10s as pixels, making a 400x400 grid.
  • Updating PlaceData shortcut values (called Retag right now, despite not actually editing tags) is now resumable and works correctly again.
  • Added warnings to PerfData if users login with the username and password in the URL instead of body.
  • MapTileController endpoints that take a location can now read the inputs from the body instead of the URL to keep locations out of logging.
  • Added a new GameTool, GeometryBuilder. Takes a list of PlusCodes as points, and can create a simple polygon from them. Does not attempt to re-adjust points in the list except to make a closed shape at the end. Still in process, incomplete.
  • Added Server/Logout, so you can immediately revoke login credentials instead of waiting for them to expire automatically.
  • Fixed some duplicate MatchOrder values in mapTiles styleSet
  • Added a new styleSet for processing purposes: importAll matches on all tagged entries. This is intended to be used for loading everything initially from a PBF file. This is probably ideal if you would prefer to edit a style from a database with elements to see them appear live.
  • PbfReader can now handle mulitple style sets at once, so you can load mapTiles and adminBounds in a single pass, instead of doing 2 loads of a source file or using importAll.
  • Loading data from PMD files now respects server bounds, so loading entries after DB creation will skip items that are outside the server's limits
  • The Place table now stores the name for each place in the main row, instead of parsing tags on each loaded item. This change, when loading items by matched style using PlaceData entries, generally means tags will not be needed by a game after the initial load.

Larry:

  • Larry can now make V2 offline files. Unlike the plugin, Larry runs them in parallel and can save them to files or the database.
  • OfflineV2 data sets can be merged together by Larry. Use -mergeOfflineSets and point at a folder with sub-folders containing the offlinedata by styleset. EX: Use this to merge a mapTiles and an adminBounds set of data into one set containing both.

Plugins:

  • Offline Data Plugin now has a V2 that dramatically increases usability.
    • /Offline/V2/{plusCode}/{styleSet} compresses all data in the given Area matching the requested StyleSet, and sends over reduced Geometry along with a nametable of each unique name in the area requested. A client can use the Geometry data to draw the maptile locally, if the client has rules for the matching styleSet. This text data is approximately an order of magnitude smaller than the data on the server for the same area.
    • /Offline/Style/{styleSet} will convert the styleSet on the server into a client-usable format to draw with later.

Release 11

02 Dec 16:34
Compare
Choose a tag to compare

Release 11 has a lot more changes than I originally expected it to. One of my constantly repeated notes across my docs is "Don't try to run a global-scale game", and I've chosen to ignore my own advice and see what it takes to do that anyways with a new 'core' game. It has taken quite a bit of time since the last release, but it's also revealed a lot of optimizations and better approaches that should benefit games of any scale.

I continue to think that my simplest bootstrap process is my best, and have found some fragility in the previously-preferred geomdata/tagsdata file loading process as I make changes and expand on what PraxisMapper could or should do and increase the options available. The next release may well focus on cleaning up that and PbfReader to make it simpler/easier to set up larger instances.

The biggest core change is that I now use TagParser on each Place when loading it to the database the first time, and save all matched styles to the PlaceData table. Pre-tagging styles to Places this way allows the database to match on a given style without loading every geometry and passing that to the C# server. This is the biggest optimization that allows for maptile drawing and searching for specific entries to be dramatically faster.

Core/Server:

  • New GameTool: PointPicker lets you ask for a number of individual Cell10s (or 11s, if cellSize is set to 11 instead of 10) inside a given area or polygon. By default, attempts to ensure that a third of the points are in a walkable location (trail or tertiary road assumed to have a sidewalk) EX: can ask for 20 Cell10s inside a Cell8. Potentially useful for quickly determining random spawn points for items or enemies.
  • A new PMD file format has been set up to replace the geomdata/tagsdata intermediate files. The new format is a single file, self-contained, significantly smaller, and should be very easy to drop into an existing database to add or update contents. It supports resuming after stopping and limiting results to bounds, handles processing modes on read (full data should always be written). It does not currently support splitting a PBF into 1 file per style entry the way that PBFReader does.
  • GeometryTracker is now 2 classes. CellTracker handles storing and casting an arbitrary list of PlusCode cells to Geometry for drawing purposes, and is dramatically faster for this purpose when only tracking cells to be drawn. GeometryTracker specifically handles arbitrary geometry objects and no longer has the AddCell/RemoveCell calls on it because CellTracker is the correct way to handle that.
  • A new StyleSet was added. AdminBoundsFilled is split into each possible value for admin bounds and draws them in a static-random color (the color is random based on the places name, but its the same color every time for that particular name)
  • AdminBounds, the original style that draws the dashed lines to indicate boundaries, has been adjusted to look a little better.
  • AdminBounds and AdminBoundsFilled should pick the primary, complete geography for a country more often, instead of every piece or component of a country's border or administration.
  • suggestedMini style has been repurposed: It is now the smallest set of reasonable playable locations for a location-based game (park, university, natureReserve, cemetery, historical, artsCulture). This set can handle a global server in under 25GB of storage space, including indexes and PreTag info.
  • suggestedMini style has also had the M de-capitalized now when actually used.
  • ArtsCulture now has all of the relevant entries from the Tourism category added to it and is the appropriate gameplay style.
  • Tourism is now exclusively lodging, and is no longer a gameplay style. It has also been removed from SuggestedGameplay and SuggestedMini styles.
  • MapTiles no longer matches admin bounds with a transparent entry in the mapTiles style set. This should speed up drawing maptiles after data is pretagged, but does mean that loading admin bounds into a database requires a second pass across the source PBF file specifically for them.
  • teamColor style was expanded to 8 values (red, green, blue, white, orange, teal, yellow, pink) and now uses color names instead of number IDs
  • teamColor style has an outline entry added, which can be used to draw a black border with no fill color for use when you need to draw a thing that you want to appear.
  • teamColor outlines are now fixed-size at 5px
  • StylePaints can now draw a random color based on an entry's name tag. This is used in AdminBoundsFilled.
  • Water polygons processed from shapefiles will now always be drawn under other elements in the mapTiles style.
  • SkiaSharp will now draw icons from an internal cache instead of reading the bitmap file every draw.
  • Added Place.RandomPoint() to pick a random point inside a GeoArea or Polygon[using the envelope of Polygon, so points may not be perfectly in bounds].
  • Added GeometrySupport.GeometryFromWKB(byte[]) to read Well-Known Binary formatted geometry objects.
  • Added Places.GetPlacesByData. Use this to query places on a PlaceData key/value pair. This is intended for use with the new feature in Larry to tag-match all places and save the result.
  • Added Places.GetPlacesByTags. As above, but searches for existing OSM tags. Doesn't need you to run Larry with the -preTag command, but won't replicate results of any style that uses more than 1 key/value pair, which is most of them.
  • Added GeometrySupport.CalculateDrawSizeHint(Geometry, ICollection). This lets you determine the draw size hint for a standalone Geometry object if you know how you want to paint it. Used by the below function.
  • Added MapTileSupport.GetPaintOpsForGeometry. This is intended for when you have a Geometry object that isn't a Place (EX: CellTracker.ToGeometry()) and know what style you want to paint it. You can add the results to the list from GetPaintOpsForPlaces() and draw the two together.
  • Added ImageStats.FitToImageSize(GeoArea). This leaves the set image size in pixels alone, and changes the area to fit the aspect ratio of the existing pixel size values while fitting the entire requested GeoArea inside those bounds.
  • MapTileController can now draw Places from a single matching entry in a StyleSet. In the URL, add the single style you want to draw between the styleSet and zoom entries for Slippy tiles, or after the StyleSet for PlusCode tiles. This is not available for drawing Area data.
    • EX: MapTile/Slippy/adminBoundsFilled/city/10/272/390.png
  • Can now call TagParser.PickName() instead of TagParser.GetName() in a plugin to avoid getting errors about references that aren't actually needed.
  • allowList moved to config instead of code. You can now add paths to the comma-separated list in appsettings.config to change which paths work without logging in. Useful if you change if MapTiles are or are not allowed by anonymous requests, and for adjusting plugin call access.
  • Places.GetPlaces now allows you to search on a tag key or value, and a data key or value. This still uses the spatial index and requires an Area to search. EX: You want to figure out which country covers a Cell10, you could set tagKey = "admin_level" and tagValue = "2".
  • GetPlaces() has a new optional flag: skipType. If passed, it will specifically skip items pre-tagged with that styleSet when loading from the database. AdminBounds are usually the largest and most complicated entries available when those are present in the database. This flag is generally a huge increase performance when set and admin bounds are not needed. (EX: the United States relation is 2.2MB by itself, and if the boundary isn't being drawn is a lot of data transferred from the db that isn't needed).
  • GetPlaces now sorts by DrawSizeHint instead of area/length. This should be much faster and provide equivalent results, since drawing was re-ordered by DrawSizeHint anyways and most other calls that depend on order only needed First() or Last().
  • MapTiles.DrawAreaAtSize() now has a skipType parameter that's passed to GetPlaces. In quick testing, this cuts a 2,000ms call down to 90ms when admin bounds are present on the server and "adminBounds" is passed in.
  • GenericData's calls can be cached automatically now. Requires setting "enableServerCaching" to true in appsettings.json to use.
  • MapTileSupport (and therefore MapTileController) can now cache map tile data automatically now if "enableServerCaching" in appsettings.json is true. Images will be pulled from or added to the cache when GetExisting[Slippy]Tile is called.
  • MapTileSupport.SaveMapTile and SaveSlippyMapTile can now be passed an expiration date. This is the absolute date the tile expires, not a difference in time like the expiration values for the GenericData calls.
  • bannedReason column added to the authentication data table, so admins can track/remember why a ban was set on a user.
  • PBFReader usage is being simplified. The default plan will be to read .osm.pbf files and write them directly to the database. This will handle creating and updating a database from source files in a single command. Entries will be run through the PreTag command to allow searching Places by style db-side. The previous suggested plan of processing data to geomdata/tagsdata files and then bulk loading those is being deprecated. The new way is slower because EntityFramework actions must be single-threaded, and a database read per group occurs, but this way can be done live on a running database.
  • GenericData.DeserializeAnonymousType(string, T) added. A helper to decode JSON into an anonymous type. Intended for use when a call is the only place a particular object type is used and you don't want to make a new class for it. Probably also works on non-anonymous classes too, but thats's not likely necessary.
  • The server now allows you to directly do some GDPR requests as a user. Go to /Server/Gdpr to get to the managemen...
Read more

Release 10

29 Jun 19:17
Compare
Choose a tag to compare

Release 10 runs on NET 7. Plans to build on NET 8 have been scrapped, as dependencies I use no longer make a beta build working on the development version of NET available.

This release adds in some logic to make likely searches simpler, GDPR compliance to some extent, and another demo named RoutineBreaker.

Core:

  • NameGenerator now adds English vowels, consonants, and a {makeword} token to generate a random, plausible word out of them.
  • New function: GeometrySupport.UpgradePointToArea added, pass it a Point and it'll return the smallest geometry surrounding it. Can also be limited to a matching style in a styleset, so you can limit this to 'building' or such if you know you want a particular Place to draw it as.
  • New GameTool: MeterGrid allows you to create custom grids based on their size in meters. This is the same math used by Orna and GPS Monster Scouter to create gameplay grids, and I believe both of those use 500 meters as their values. Can directly save to and load from the AreaData table, including secure options.
  • New extensions for converting distances in degrees or meters to the other unit, using DistanceDegreesLatToMeters , DistanceMetersToDegreesLat, DistanceDegreesLonToMeters , DistanceMetersToDegreesLon. This should make using linear distances simpler.
  • Added Place.FindGoodTargetPlaces, which lets you search for Places that are inside another Place and within a min/max distance. This is intended to help pull up locations to ask a player to visit that are worth driving to (EX: Finding a historical/tourist/cultural point inside a park/nature reserve/university). This returns the inner points of interest. Use this to pull up a historical marker in a nature reserve.
  • Added Place.FindParentTargesPlaces, which uses the min and max distance to find all Places that cover other Places. This returns the list of parents that cover points of interest. Use this to pick the nature reserve with historical marker(s) in it.
  • Added Place.FindAnyTargetPlaces, which uses the min and max distance and then simply returns all places found in the style set without further filtering.
  • Added Place.FindPlacesInPlace, which returns all Places inside the given Place that are a game element style. Useful for when the player is in a large Place and might want to visit Places inside (EX: At a nature reserve, are there any other Points inside it specifically to visit). Also possibly useful as a very simple scavenger hunt list.
  • Added Place.GetPlace() to pull all the data on a single Place by PrivacyId.
  • Various optimizations across the app.

Server

  • New Endpoint: /Server/GdprExport allows a logged-in user to receive all data stored about them specifically.
  • New Endpoint: /Server/GdprExport/{username}/{password} allows a user to receive all data stored about them specifically without being logged in.
  • Now shows some local IPs that Kestrel is listening on after startup is completed.
  • Splatter demo now server-side validates a player has points to spend before spending them. Was previously client-only.

Larry

  • Processing coastline water polygons has been fixed and improved.
  • Fixed skipping blocks when stopping/resuming PBF processing.

Demo:

  • RoutineBreaker demo: A demo that keeps a list of places you've visited, and pushes you to go to new Places. Client included in the /Content folder.

Release 9

25 Mar 17:38
Compare
Choose a tag to compare

Release 9 fixes a couple of significant bugs in Release 8, and adds in a Demo plugin.

PraxisCore:

  • GeometryTracker now allows adding and removing arbitrary geometries.

SkiaSharp:

  • Fixed a significant bug on drawing multipolygons, causing overlays with transparency to shift colors.

PraxisMapperServer:

  • New Plugin: DemosPlugin handles logic for the demo apps. First one is Splatter, which lets players walk to build up Paint points and tap the map to throw paint at that point. Uses some GameTools to demonstrate how to use them in a game plugin. Enable PraxisAuth in the appsettings.config file to have users build up their own personal paint supplies, or all users will share a total of paint points and recent history.
  • MaintenanceMessage checks a better set of string values to allow through.
  • TagParser is now initalized before and after plugins are loaded, so plugins do not each need to do it.
  • Fixed issue during login that can happen in limited scenarios

Release 8

19 Mar 14:48
Compare
Choose a tag to compare

Release 8 contains a lot of logical clean-up and makes things somewhat easier to read and understand. Because of all the renames and rearranging, this is a release full of breaking changes. Hopefully this ensure that there are fewer breaking changes in future releases as we get them all out of the way now.

The other major addition is greatly simplified server setup. Get a PBF extract, set 1 config value, and run PraxisMapper.exe to get going as fast as possible. Full instructions with an example are available here

This also contains the first set of entries in the GameTools folder. These are things you are likely to want to do in a location-based game, consolidated into simple components that do their best to adhere to the minimum-tracking philosophy PraxisMapper espouses. DistanceTracker in particular is a common thing in location-based games.

This release is built using NET 7. This is almost certainly the version you want to use for now, barring any bugfixes. As usual, Linux/OSX users will need to download the source code and compile on their own machines. Per PraxisMapper Policy, the next big release will be done using a preview version of NET 8. It'll be interesting to see if that impacts anything.

Full changelog:

PraxisCore

  • Now suppports SQL Server LocalDB as a backend database. This is free, and removes a lot of configuration required compared to normal SQL Server, but is limited in the same ways as SQL Server Express is. This is an excellent choice for county-sized games, or for learning how to work with PraxisMapper without the excess work of managing a full-featured database.
  • GameTools namespace has been added, containing a few simple classes that are likely to handle common behaviors. Note that these usually save location data, and should absolutely only be saved using the Secure data calls to keep them encrypted for a player's account.
    • DistanceTracker will measure how far in total a player has moved since the last Add(Point) call. Includes an optional speed cap setting to ignore distance found over a certain speed. Allows you to reset the last point referenced separately, so you can resume tracking over client sessions. This saves the most recently added point internally, and includes the timestamp of that position if the speed cap is enabled, and therefore MUST be saved securely.
    • CustomGrid allow you to set up your own PlusCode like square grid with custom sizes and layers. Cells in a CustomGrid are referred to with pairs of integers. These can be used to save to the AreaData table, and can save securely or not. If this data connects a player and a location, this MUST be saved securely.
    • GeometryTracker saves a Polygon of all PlusCodes that have been added to it. This can be used to draw location history to an image, or do more complicated interactions between Geometries on teams. If this stores data on a player, it MUST be saved securely. This is the slowest-performing of the GameTools classes.
    • RecentActivityTracker stores a list of PlusCodes and removes them from the list after a set number of hours (default 22) has passed. This is intended to allow rewards granted from walking to only be granted on a regular schedule, and not spammed by GPS drift or walking in a small loop. This MUST be saved with the SetSecureData calls when it ties players to locations, even temporarily.
    • RecentPath saves a list of points, and clears itself out if an amount of time (180 seconds) goes by without an update). This can be used to make results similar to that seen in exercise tracker apps from Fitbit by drawing it overtop of MapTiles. Since this is very precise location, this MUST be saved securely.
    • NameGenerator allows the server to generate names that match a pattern provided to the class. (EX: NameGenerator.GenerateName("{animal} {number}" could return "Wolf 328") Can be passed a PlusCode string to use the seeded RNG value and provide the same response every time. You can add new tokens by inserting a List to NameGenerator.nameSets with the token you want, and it will be available to all instances of NameGenerator.
  • Added a SimpleLockable class that makes it easy to keep calls from clobbering each other when updating the same values.
  • PBFReader class has been reworked internally. It now supports Planet.osm.pbf correctly (previously only worked with extracts from geofabrik.de and similar files), is a little smaller and cleaner, and several bugs were fixed.
  • PMFeatureInterpreter had some longstanding bugs removed, should reduce the amount of Relations that don't get interpreted into Geometry objects. Should also be slightly faster.
  • About 25 new drawing rules have been implemented for the main MapTiles drawing style. None of the new elements are gameplay-specific, but should bring results closer in line to OSMCarto.
  • Expanded the Arts & Culture style. Now includes convention centers and libraries, among other entries.
  • Removed coastlines from the default styles. Reason: They're of little use in their baseline state out of a PBF. They need to be constructed into polygons and imported from https://osmdata.openstreetmap.de/data/coastlines.html . Imported coastline shapefiles are now tagged as 'natural=water' to ensure imported data gets rendered by the styles.
  • AdminBounds style now draws at fixed-widths.
  • SuggestedGameplay style now draws on a white background. It works better as separate tiles rather than as an overlay.
  • Added 'suggestedmini' style. This allows entries to be matched on a single tag rather than multiple. Intended for use with the new minimize process
  • Added GeometrySupport.SpeedCheck(point1, time1, point2, time2) to determine how fast a player went between 2 points.
  • Can now use GeometrySupport.MetersDistanceTo() to find distance in meters between 2 PlusCodes, Points, GeoPoints, or pairs of coordinates.
  • New extension method for working out distance between 2 Points, 2 GeoAreas, 2 GeoPoints, or 2 PlusCodes in string form.
  • New extensions to make fixing invalid geometry or simplifying geometry quicker to code.
  • New extension to convert an AreaData row into a DbTables.Place, when such a conversion is necessary.
  • New extension: DateTime.ForwardToMidnight() will take given DateTime and advance it to midnight. Used in game plugins to set expiration dates for data.
  • TagParser now handles inserting styles instead of it being done manually.
  • added a FixedWidth rule for styles. If set to a number > 0, it will always draw elements of that style at this size in pixels wide.
  • Optimization: added DrawSizeHint to Places. Contains how many pixels a Place will require to draw at the default gameplay tile scale. Replaces AreaSize in existing databases. Previously generated geomData files will need to be regenerated.
  • SearchArea/SearchAreaFull are now significantly faster than before, especially after PGO is completed.
  • Loading files into the database will drop existing indexes before starting.
  • A bunch of class names got changed:
    • AreaTypeInfo is now called AreaStyle.
    • TerrainData is now AreaInfo.
    • FindPlaceResult is now AreaDetail.
    • FindPlaceResults is now AreaDetailAll.
    • SearchArea is now GetAreaDetails.
    • SearchAreaFull is now GetAreaDetailsAll.
    • FindPlaceInCell10 is now GetAreaDetailForCell10
    • FindPlacesInCell10 is now GetAreaDetailsAllForCell10
    • Place.GameElementType is now StyleEntry, to better convey the field's purpose.
  • A bunch of database tables are also renamed
    • AreaGameData => AreaData
    • PlaceGameData => PlaceData
    • GlobalDataEntries => GlobalData
  • PlaceData is now accessible from a Place loaded from the Entity Framework.
  • GetPlaces no longer has a boolean to indicate if points should be drawn or skipped. This logic is now handled automatically by drawSizeHint values.
  • GetPlaces has a new boolean flag, skipGeometry. If true, the database search will be done without sending the elementGeometry data to the server. This can be useful for working with the Tags present without spending extra RAM on geometry. Set filterSize to 0 with this call to ensure all elements are read.
  • Several of the core plugins now copies themselves to a useful folder after building.
  • OpenLocationCode.DecodeValid will now accept a + in the string (and remove it automatically)
  • GetNearbyPlaces is now usable. Pass in a Point or a PlusCode and a distance in degrees, and get back each Place within that distance and the distance to the point.
  • TagParser has been reworked to be more usable with parent object instead of their tag collections. Function names are also consolidated
  • TagParser now has GetTagValue(Place, string). Checks both PlaceTags and PlaceData for an entry with the given key.
  • 'Internal' passwords (the ones used to store data on a player in a way the server owner can't read) are now stored in the same table and row as their Login password.
  • Renamed "WriteToFile" property to "SaveToFile" in Log class.
  • GenericData now saves significantly faster for all saving functions.
  • FromTag behavior changed on StyleEntry : If FromTag is true, PraxisMapper will search for a tag or PlaceData entry with a key equal to the matched style's name. The built-in 'paintTown' style shows this working with a single entry: 'ptcolor' is a style that matches everything, and any entry with a tag/PlaceData key 'ptcolor' will be drawn in the color given in that tag/data's value. It's easier than I'm making it sound, I swear.
  • Removed a bunch of MapTileSupport functions that had their logic consolidated into the main GetPaintOps path.
  • GetAllData calls now return the rows found, instead of populating a custom class. NOTE: when doing this for Place, you'll get back the integer ID. Don't send this to client apps, use the GUID you passed into the function.
  • GetExistingSlippyTile has been moved into MapTil...
Read more

Release 7

28 Nov 15:46
Compare
Choose a tag to compare

Release 7 primarily focuses on expanding features into plugins that can be added or removed from a server as needed, and expanding the authentication setup to handle more complicated applications. Much of this mirrors development on TIBO, the official application I built and the base of the CreatureCollectorClient repo.

The attached binaries are built for Win-x64 systems. Mac and Linux users are encouraged to download the source code and compile locally to ensure everything runs on your particular system correctly, and remember to use ImageSharp for maptiles instead of SkiaSharp. The release includes all of the core plugins in the solution. See the wiki tab here on Github for documentation on endpoints and making your own games.

General:

  • Now running on the official NET 7 release instead of previews. NET 7 must be installed for PraxisMapper to run.

PraxisCore:

  • Added .GetSeededRandom() extensions to help procedural generation logic. EX: If you're naming an area but not storing names in the DB, you could call "85633Q".GetSeededRandom() and then that Random() can be used to generate the same name every time. Should be unique for Cell6s and larger areas, will definitely have duplicates somewhere on the globe for Cell8s or smaller.
  • A Mersenne Twister implementation was added to CoreComponents if Math.Random is insufficiently useful
  • Added .PadGeoArea(padding) extention to GeoArea. Returns a new GeoArea with the given padding value added to all sides of the original.
  • Expose GenericData.Encrypt/Decrypt functions, so secure data can be created/used in commands not currently built-in to GenericData (EX: loading all data over a place with a specific key)

Larry:

  • Larry can now successfully update an existing database's with new geometry entries. Use -updateDatabase while the server is live to handle everything seamlessly, or use -updateDatabaseFast while the server is down to get through processing a little faster.

PraxisMapper Server:

  • New Plugin - PraxisVersionPlugin. Lets clients ask for the expected client version, will let them know if they are not up to date with the server.
  • New Plugin - PraxisMunicipalityPlugin. Lets the client ask what the smallest admin_level entry is for the Cell10 PlusCode given. Also allows replying back with all entries with all places and admin_levels in the given PlusCode. Also allows clients to get the Place name (or terrain type) for a Cell10.
  • New Plugin - PraxisOfflineDataPlugin. Reads the database and crunches data down to be as small as possible, for use without a network connection. May be generated ahead of time and included in an app, or requested by a client to get only relevant info on-demand.
  • Added MapTileSupport.SaveMapTile(), so that tiles generated outside of the MapTileController can be saved to the database and have their generation tracked correctly.
  • Added MapTile/StyleTest endpoint to get a viewable image of all the given style set's entries.
  • Added /Server/RandomValues/pluscode/count endpoint. Ensures the client can use the same random values as the server for an area.
  • PraxisAuthentication will log calls that fail to auth to the PerformanceData table if logging Performance Data is enabled.
  • GetAuthInfo() has been moved from PraxisCreatureController to PraxisAuthentication.
  • Fixed Places.RandomPoint() to return values inside the bounds given.
  • MapTileController calls no longer log the PlusCode they drew to PerformanceData entries.
  • PraxisPerformanceTracker has a new static method to call to just log something quickly to PerformanceInfo table.
  • Add count to ExpireMaptiles calls as return value.
  • Plugins can now set a list of endpoints to allow-list without requiring a logged-in user to access. Add the endpoint path into the list at PraxisAuthentication.whitelistedPaths. Requires referencing PraxisMapper.dll in addition to PraxisCore.
  • Accounts can now be banned at the server level by setting the bannedUntil value on their entry in the AuthenticationData table to a UTC time in the future.
  • Accounts can now be marked as a administrator in the database. Controllers can now call PraxisAuthentication.IsAdmin(accountID) to block non-admin users from running a particular function.

Release 6 - 2nd Anniverary

13 Aug 12:53
Compare
Choose a tag to compare

Release 6 is largely a quality-of-life improvement for the server, shortening the amount of code that needs written to do common things. Several of these additions are things I realized I need as I worked on my own game built around the server. This is also the end of the 2nd year of development on PraxisMapper!

  • Added .PickOneRandom() extension methods to Lists and ICollections in PraxisCore for convenience in plugins.
  • Added .ToPoint() extension on GeoArea, to get an NTS Point at the center of a PlusCode.
    • Added extension methods to make it faster (for developers) to save or load data. Can use .ToJsonByteArray() on anything when saving and then use .FromJsonTo<T>() after loading data from GenericData endpoints. Other helpers for some cases where casting straight to JSON were also added.
  • Moved DELETE /Server/Player to DELETE /Sever/Account, includes auth data entry now.
  • Plugins can now have a class implement IPraxisStartup, to have a static Startup() method run once when the plugin is loaded. Useful for setting up values that need calculated or loaded once or any other prepwork a plugin might need.
  • Pluigns have been moved to the /plugins folder, reducing startup times.
  • Can now select a random point inside the server's boundaries through Place.RandomPoint() or /Server/RandomPoint.
  • GenericData can now search all player's data for a specific key. Intended for things like leaderboards.
  • GenericData calls can now automatically serialize an object to JSON before saving, and can deserialize JSON to an object automatically. Cuts down on how much typing is needed for saving and loading complex objects.
  • Data/Terrain and Data/Terrain/All can now search on any style set to process results. Useful for in-game terrain types versus OSM map tag terrains.
  • Creating an account on the server automatically creates a 'password' entry for the user with an auto-assigned internal password by the core server instead of expecting plugins to do it.
  • GenericData.GetInternalPassword() added, primarily to be used by PraxisAuthentication on login.
  • Added a new GetPaintOps method that calls TagParser to determine the style on each element, instead of using game element name.
  • IsInBounds() can now have a single member set and have that always checked against for convenience.
  • ImageStats now has a constructor with a single PlusCode string as a parameter.
  • Points are now drawn automatically on the map based on the size of the image for ImageStats constructors. Default can still be overridden after creating the ImageStats object.
  • Other small bugfixes and security improvements.

Release 5

21 Jun 02:25
Compare
Choose a tag to compare

Release 5 changelog:

  • Added an Arts/Culture category to default tags. It has a fair amount of overlap with the Tourism tag, so there may be some debate internally on if this gets merged into that.
  • Added a NamedBuilding category to default tags. Should help identify buildings that are more likely to be public/notable from private buildings like houses, and possibly identify buildings that aren't tagged as anything else but have points contained in them that are.
  • Better use of middleware on startup, makes everything just slightly faster.
  • Added a per-user-login PraxisAuthentication logic. Can replace or complement the per-app PraxisHeaderCheck logic. New auth requiring creating an account and logging into it before any other calls will succeed. The header check may remain useful early on in a game's development, or for games that don't require player-specific data.
  • Added early anti-cheat feature: requires each user to upload specific files to the server to validate that they're using a valid copy of the expected client. Should prevent most modifications to a client-side game from working if used on some kind of code file, assuming code files could be read by the game running it.
  • PraxisMapper will now load DLLs with a class that implements IPraxisPlugin from PraxisCore and use any controllers or views defined in it. This allows you to write new endpoints for the server without editing the core code.
  • Data/Area/All calls no longer grab entries that share a border with the requested Cell
  • The secure options for saving/checking a user's account/password have been moved from /SecureData to /Server.
  • New option for splitting a PBF file into separate output files by tagged area.
  • Endpoints now offer a replacement path value to hide sensitive data from PerformanceTracker when its enabled.
  • Data, SecureData, StyleData, and MapTile endpoints on the server can now be blocked from external calls. This allows a plugin-driven game to be server-side authoritative by ensuring clients never access data directly. This is not necessary for games with a small audience or learning the system, but allows more professional work to be done overtop of PraxisMapper.
  • New endpoint: /Server now handles some commands that apply more to the infrastructure of the server or game than actual in-game data, like boundaries.
  • Can now do /Increment calls on the SecureData endpoints.
  • Message of the Day support added, on /Server/MOTD
  • Maintenance message can be set that blocks all endpoints from returning their usual data, and instead sends the maintenance message.
  • Other optimizations, security updates, and bugfixes

Release 4

20 Apr 03:18
Compare
Choose a tag to compare

Release 4 is mostly a bugfix release. No new features were added to the server, but dependencies were upgraded, bugs fixed for features added or improved in 3. This version works with the Release 2 of Hypothesis out of the box, to make starting development on a GPS game with PraxisMapper as fast as possible.

  • Updated to NET 7 (Preview 2 as of this writing) and corresponding NuGet packages.
  • Larry now has a setting for how resource-intensive it should be. 'low' forces single-threading, and 'high' keeps as much data in RAM as possible.
  • Fixed encryption for SecureData endpoints occasionally erroring out.
  • Fixed uploading and download binaries from Data/SecureData endpoints.
  • SecureData endpoints for Encrypt/Decrypt User Passwords no longer save to PerformanceTracker entries. SecureData endpoints for OTHER entries (player/place/area data) will send back a header indicating that performance tracking is enabled and values are visible in the database, allowing the server host to see how performant the SecureData endpoints are. It is strongly advised to both not use 'good' passwords for game purposes on these elements (because guessing some hidden stash was locked with the password '12345' is fun for those that find it), and not to reuse real passwords from other services. The Encrypt/Decrypt endpoints are intended to be a start for a proper user authentication process, and should be treated with maximum respect for privacy.
  • Small optimizations to several functions across the app.
  • More bugfixes

Release 3

17 Mar 03:01
Compare
Choose a tag to compare

Release 3 is a significant improvement over Release 2. This is the first release that I would expect to be usable for anyone else to build a game with. It is still at least an Intermediate level of difficulty, as it requires some knowledge of database setup and web server configuration. Hypothesis will NOT have a corresponding release, since the GeoCache mode depends on a couple of features that aren't working in this release after all.

I might not have listed every change, but the biggest ones should be written below:

  • Larry now has a -makeServerDb command, which takes your pbf files, processes them to the intermediate TSV files, and then uploads those to the database in a single command.
  • Code cleanup done. Old tables and variable names should now match the concept they represent instead of a technical working name. Unused columns have been removed from the database. Close to 2,000 lines of code, comments, and whitespace have been taken out.
  • Output files have now been standardized into a tab-separated values format. GeomData holds the Place entries, and tagsData holds the PlaceTags entries matching the DB tables. The TSV files are much more compact and take up significantly less space than JSON formattted data, and are faster to load into the DB at the cost of splitting data into 2 files. Coastline processing should be hard-coded to output appropriate style info.
  • New Styles: A total of 4 default styles are included: mapTiles (roughly OSM defaults), outlines (everything gets a black outline), adminBounds(only draws cities, states, countries, etc), teamColor (A simple style for taggings areas by a team or faction), and paintTown(An example style for a client mode, that draws a color defined in the tag)
  • Server's Performance Tracker class is now ASP middleware, so it logs all calls to all endpoints and their runtime. Can read a custom header (X-notes) to save additional data on a call.
  • Performance boost: The functions for turning a PBF into intermediate files and loading those intermediate files into a DB are now dramatically faster. This is the biggest change, but most areas of the app have also seen small optimizations to keep the server performant.
  • You can now run the core PraxisMapper executable to start up a working webserver without IIS/Apache/etc. This dramatically reduces how much effort is needed to go from nothing to a game server. You can still use a heavy duty webserver in front of the app as before.
  • PraxisMapper now supports multiple drawing engines. Included in the project are 2: SkiaSharp (The Windows default) and ImageSharp. SkiaSharp is faster and handles anti-aliasing small details better, but ImageSharp doesn't require any external dependencies and works on Linux without jumping through any hoops. Each engine is handled in its own DLL project now, and which one is loaded at runtime as determined by the configuration setting.
  • APIs have been renamed to be REST style, and are a good deal shorter and more obvious on their purpose.
  • Clients can now ask for what version a maptile is on, and can track that to know when it needs to download a newer version of the time instead of redownloading every tile every time.
  • Old code that was specific to a game mode or idea I was working on is removed from the server core.
  • Performance Assumptions: A county sized game (500 mi^2) should run decently fine on an AWS Micro server (2 CPUs, 1 GB RAM) on Windows/Linux for some double-digit number of players. A State sized game (50.000 mi^2) will load on an AWS Micro server but takes dramatically longer to draw map tiles under any load. A Continent sized game will require a minimum of 48GB RAM on the database alone to handle indexes for Place data, and more for MapTiles as users start populating information. Actual results may vary with density of data.
  • A bunch of bugs were fixed.