Solved Advanced world resource placing problem

Discussion in 'Spigot Plugin Development' started by ItsLars, Feb 15, 2019.

  1. Hello Spigot.

    For a certain project, I have a small problem. What I'm trying to achieve:
    I need a world, in which players are unable to dig into the ground, but are able to cut trees and mine stones that are spreaded across the map. These trees and stones have to respawn in the world a certain amount of time later.
    I did manage to create a system that works very nice:

    1. We created a world in worldpainter, empty of trees, stones, and practically anything that's on top of it. Just the biomes.
    2. We made a set of schematics, containing all kinds of trees, stones, and other stuff to be placed in the world.
    3. We ran a populator, that randomly places the schematics across the map (with FAWE api), based on the biome we're in. For example: in a Plains biome, 70% of the placed schematics is an oak tree, and 30% a rock.
    4. Every placed schematic gets a unique ID, and is placed in a 'resourceInfo' table in a database.
    5. We retrieve the minimum and maximum corner of the schematic, and loop through it. All blocks that belong to the schematic (logs, leaves, stone, etc.) are placed into a 'resources' table into the database, together with the UID of the resource they belong to.
    6. When a player mines a block, we execute a query that retrieves the UID of the resource that the mined block belongs to, from the 'resources' database. We then remove the entire resource, and give the player the item he should get.
    7. After a certain amount of time, the exact same schematic is pasted back at that location.
    This system works, but there one problem. It takes a little bit too long.
    In a 1000*1000 world, there are about 3000 resources pasted into the world. All these resources together have about 250.000 blocks that are stored in the database.
    When a player mines a block, the query that has to select the UID takes about 0.7 seconds. Since we will expand the world size and amount of worlds, the time it takes will definately go up.

    We have thought of a solution, that is based on generating a table in the database for every biome in a certain world, which would obviously be a lot quicker, since the size of these tables wouldn't be so large.

    However, this is also a bit unpractical, since that would mean that we'd get a relatively big amount of tables in the database.

    That is why I'm asking if anyone has a better solution to this problem, or maby even an alternative to the entire system that might work faster.

    Thank you for your help, and feel free to ask any questions if something is not clear.
  2. First idea: If you are working with 1.13 you could try to give each schematic a BoundingBox and get the box of the vector, pointing to the mined Block.

    Second Idea: create ProtectedRegions from Worldguard for each Tree/Rock and name it after its respective UID.
    On block break -> get protected region -> get name -> lookup name in database
    With this you can directly perform FAWE actions with this region.

    Third idea: Map Cascade
    (You could expand on this with Worlds and Biomes)
    Map<Double<Map<Double<Map<Double, UUID>>>>
    On block break -> get location x,y and z -> get ID from map.
    This should be pretty fast. With a TaskChain you could search async and act sync.
    #2 7smile7, Feb 15, 2019
    Last edited: Feb 15, 2019
  3. Saving the blocks in a map instead of in the database would probably indeed be quicker, and also easily expandable with worlds and biomes to increase speed even further.
    I don't know what the impact on the RAM will be however, if we're going to save millions of blocks in maps.

    Thanks for your help, I'll look into it!
  4. The system works now, and it's really fast. Then again, a new problem occurs; the impact on the RAM is very big. One world uses about 500MB of RAM, and since we're looking to use about 10 worlds, this would obviously come down to 5 GB RAM.
    I'll keep looking for ways to decrease the RAM usage or alternatives to this solution.
  5. Hey itslars!
    mag ik een screen met je in minecraft

    For the english guys..
    This is a dutch youtuber with 30k/40k subs
  6. Thank you all for your help. I solved the problem by creating a database table with the UID and connectedBlocks column.
    In the connectedBlocks column, all blocks of the given resource are described in the following way:
    ',[x1].[y1].[z1],[x2].[y2].[z2], ........ ,[xn].[yn].[zn],

    When a player mines a block, I search for the block coördinates in all 'connectedBlocks' fields. For 3000 resources, the query took 0.0039 seconds, which is very fast.
  7. Dang, you could save it in a db like he said.