Minecraft- 100k Timelapse Download






















Sure, you can try a hundred a second. Imagine you did a cute little spiral going out from 0,0. Since render distances are 9 by 9, we can actually just skip to one chunk in every 9. Even spiraling like this, it would take days to spiral out to where the interesting bases, in the mid hundred ks range. Very few bases have players online all the time or even most of the time. We start with two bots on offset shift schedules in the nether for continuous coverage. They scan the nether highways really, punch one block per every 9 chunks, expanding outwards on every highway and diagonal, sort of like radar.

We devised a system, using a monte carlo particle filter to simulate and track movement, that uses about 2 checks per second to keep up with a player as they travel at arbitrary speed. Elytra, boat, entity speed, sprinting, walking, anything. Even pig god mode! Even spectator mode! All we care about is if chunks are loading, that's what we can see. Basically, we built a machine that plays this game of battleship against 2b2t, really well, using up all the hundred some checks a second we get, and uses it to follow the battleships as they move around the board.

And when a battleship disappears from the nether board, we look over at the overworld board and keep going the bots coordinate with each other of course. In this way, we simply, just, follow people to their bases by keeping up with them as they load chunks. From our observation posts we can check chunks all over the map, at any distance. The monte carlo particle system simulates potential player positions and velocities referred to as "particles". As hits and misses come in, the more likely particles reproduce, and the less likely particles are culled.

Across many generations, the population settles down around a very accurate position and velocity, to sub-chunk accuracy after just a few generations, which are one a second. For example, for someone on a nether highway moving at a constant speed, this is able to keep up with 1 check a second, once it gets their trajectory down cold.

We also incorporated some other strategies. For example, when someone joins the server, we lookup the most recent time they left, then we lookup all the tracks that went cold within 1 minute of that time, for each of those tracks we send a few checks sprinkled around the area to try and pick up where we left off with tracking them.

A few other techniques like this allow tracking to be extremely resilient. After the massive ratelimit in May likely due to 0neb , it was just barely at the edge of what's even survivable for this exploit, but we pulled through, tweaked priorities, decreased scan net sizes, wrote some special cases for stationary players, and more. It's easy to forget, but this isn't just for checking chunks. We created a very efficient base downloader by essentially "paint bucketing" or "flood filling" the modified blocks compared to 2b2t's seed to get all ground level structures.

You'd be shocked how far people go out, millions of blocks, just to build a tiny fishing hut and afk. It seeks out the locations in the chunk with the most changes, and rechecks around them periodically, as often as once every thirty minutes. This allows us to keep up with bases as new buildings get built or torn down. We also redownload from scratch every three weeks. So, we don't just have coords of every base, we don't just have a world download of every base, we actually have the entire history of the construction and possibly destruction of the base, block by block, hour by hour, quite high resolution.

How do we actually make this happen, nitty gritty? The old version was super simple. A forgehax module was written to do the spiral search and write down the coords to a file. It's actually exactly the same as that elytra stash finder, except it does it remotely and doesn't have to fly. Fr1kin ran it at his house for over a year. The files would be sent and added to a website that showed em all. We had to do something a little bit more complicated here.

The base requirement was the communication between overworld and nether bots, and it sorta spiraled lol out of control from there. So, we start with the primary bot instance, which is a DigitalOcean droplet. This was picked to have the absolute lowest ping to 2b2t. This allows us to squeeze the absolute maximum packets per second out of the connection, with close to instant detection of network lag causing us to throttle down to almost nothing.

This allows the highest sustained checks per second across the day. The server ran a very cute headless minecraft we developed. It's able to save on RAM by having a single Java process have multiple fully fledged minecraft instances. To be clear, this isn't anything fake like reminecraft or a proxy. This is a true full minecraft client, just with all the rendering and keyboard and mouse stuff ripped out.

So that's the bots, but what does the master do? First and foremost it provides a layer of abstraction over the bots and 2b2t. TCP connections can sometimes drop, the bots can get kicked from 2b2t, a bot can randomly die and respawn in a different dimension rarely , etc. So, there is a system of priority based queues and checks. A "task" can be created, which is a straight line list of chunks to check. Or a task could be as simple as "check this particular chunk". The world and connection system handles the actual communication to the bots, and all that.

If a bot drops offline, the pending tasks are reassigned to another in the same dimension. If they all drop, it's held for when they reconnect. Sitting on top of all that, there is the system of scanners and filters. A scanner is something that tries to fish out people to begin with. The simple mid-priority ones are just highways. We also do the overworld ring at 2k out VERY commonly once every sixteen seconds, at the moment.

A little bit lower priority is the retry scanner, which looks at past bases and tries to suss out other members of the base that login at different times of day. It is continuous but low level: using up 5 checks a second. And finally lowest priority is the spiral scanner which just scans outward to k over and over.

It can take hours to days. It isn't really crucial, it only exists as a last resort "Well if you aren't doing anything else important, might as well". The priority system is simple and strict: all the highest priority tasks are done before any lower priority ones get to start. If all the time is spent on the filters which are highest priority , the scanners will never run at all.

Once we get a hit from one of the scanners, we turn to the tracky tracky manager. This checks if we already have a filter tracking this particular player, and if not, starts a new one. These filters are by default in monte carlo mode, as described earlier. The monte carlo mode is a great all-arounder. It has a lot of backups where, when it loses track, it's able to take more of the check budget to find them again, but when it has a good lock on their position and speed, it subsides back down to about 1 check a second minimum.

The average is a bit over two checks a second. When it thinks it might have lost someone, it can go up to ten per second, and if it's completely lost someone defined as no hits in 5 seconds , it declares the track over, it's lost them.

This triggers a hail mary check where we do a grid of 11 by 11 checks spread out 9 chunks apart. This is really expensive as you can see: that comes out to checks which is a full second of our budget. It's worth it given how rare it is. We also trigger a similar check in the other dimension, assuming they went through a portal. But when it works, it works well. When the most recent hit in this mode is within a render distance of all hits in the last 30 seconds, we switch to stationary mode.

This is because we have determined pretty much exactly what chunk they must be standing in to explain the last couple dozen hits. We switch to just checking that one chunk over and over. We slowly get less frequent, all the way down to 1 check every 8 seconds. This is 10x slower than the monte carlo mode. It turns out, the vast majority of our active tracks are using this at any given time. Generally people are either traveling, or are effectively stationary.

If they never move outside of their render distance from that point, the stationary filter will just comfortably check in every 8 seconds. If the stationary filter misses, we switch back to monte carlo since they're clearly on the move now. All of these hits and tracks are stored to the database. Every single time we get a response from 2b2t of "HIT" this chunk is loaded , we save it to a giant table of hits. We've had over three billion of these. Each hit is also associated optionally with a track.

This is what makes the data useful. Every track is assigned an ID. When a track switches modes from monte carlo to stationary and back, we don't change the track ID. But when a new track has to be started, such as when they change dimensions, it gets a new ID. To keep track of that, each track gets a "previous track id". This allows us to trace back the history of how people have traveled. A hit is as simple as an ID number, coordinate, server ID almost always 1, for 2b2t, but we've briefly ran this on 9b and constantiam too , dimension, track id optional , and whether or not it's legacy.

There are about three billion of these. A track is a bit more complicated, it has an ID of its own, the ID of the first hit in this track, the ID of the most recent hit in this track this is updated constantly , the timestamp of that most recent hit, the dimension and server ID, the previous track ID, and again whether or not it's legacy.

There are about ten million of these. For example, when a player logs into the server, we look up the most recent time they left, then we lookup all tracks that were last updated around there, give or take a minute. We take a guess that maybe this player logging out was what caused those tracks to end, so we attempt to "resume" all those tracks from that time, by just rechecking their last successful hit. A hit is as simple as an ID number, coordinate, server ID almost always 1, for 2b2t, but we've briefly ran this on 9b and constantiam too , dimension, track id optional , and whether or not it's legacy.

There are about three billion of these. A track is a bit more complicated, it has an ID of its own, the ID of the first hit in this track, the ID of the most recent hit in this track this is updated constantly , the timestamp of that most recent hit, the dimension and server ID, the previous track ID, and again whether or not it's legacy. There are about ten million of these. For example, when a player logs into the server, we look up the most recent time they left, then we lookup all tracks that were last updated around there, give or take a minute.

We take a guess that maybe this player logging out was what caused those tracks to end, so we attempt to "resume" all those tracks from that time, by just rechecking their last successful hit. This is extremely successful and is a crucial component of tracking people. Now we have the system that takes in this data and decides what to do with it. I haven't mentioned anything yet about deciding what's a base, and what's just an area someone's flying through, or how we determine who is where, or how we decide what areas we're going to world download.

This first step is called the aggregator. Every once in a while it looks through the hits table through all hits that are new since last time. It filters out hits that are within chunks of a highway, or within chunks of spawn.

It also ignores the nether. Then, it looks up our clustering entry for this chunk coordinate. This is a giant table called dbscan. Unlike the hits table, this table will only ever have one row for a given chunk coordinate in a given world.

It keeps track of all the activity we've observed at that chunk. When a new hit comes in, we mark down the most recent hit as that timestamp. We also update our list of "timestamp ranges". It's actually really simple: if two hits come in with less than 2 minutes of time in between, we make an educated guess that a player was loading that chunk for that whole duration, and we add that range from first hit to second hit to our list of timestamp ranges for that chunk.

If a new hit comes in that's also within 2 minutes of the most recent, we increase the range. If a new hit comes in that's outside the 2 minute range, we don't mark the range in between as occupied. This allows us to keep track of what chunks are actually occupied i. For example, our stationary filter will do this easily. The monte carlo filter will as well, but unintuitively. Even though it spams checks all throughout your render distance to determine exactly where you likely are, it will in all likelihood hit any specific given chunk about once a minute.

The purpose of the timestamp ranges system is so that we can keep track of how interesting a given area is, without bias by our two filter modes, which are wildly different from each other: stationary sends less than one tenth the amount of checks per second as monte carlo, and monte carlo spams checks all throughout the 9x9 render distance while stationary just checks one chunk over and over.

Creating this way to count up how much time has been spent at a given spot, while maintaining completely neutral behavior between either filter being used, was the hardest part here. Then, once any given chunk has built up 5 minutes of online time, we mark it as a node. This means that the chunk could be interesting but we don't know. This can happen in as little as 3 checks each spaced 2 minutes apart. Marking a chunk as a node adds it to a GiST index.

Whenever a chunk is marked as a node, or a node gets a new hit that lengthens its timestamp ranges, we queue it for an update by the next step. We have a "to update" table with a node ID, a lower bound, and an upper bound. These are initially set to 1 hour and 6 hours in the future. If a new hit comes in, we push the lower bound to an hour in the future from the new hit, but we don't touch the upper bound. When either the lower or upper bound is reached and becomes in the past, we update.

In other words, we schedule an update at least 1 hour in the future, but no more than 6 hours in the future. If new hits come in, it can be pushed back to the original 6 hour mark, but no further. So updates happen at least every 6 hours, and at most every hour. An update is what decides if the area is interesting, not if the chunk specifically is interesting. We query all nodes within blocks of radius, and union all their timestamp ranges.

For example, if one chunk has a timestamp range from 4pm to 5pm, and the adjacent one has a timestamp range from pm to pm, this comes out to 4pm to pm, so we would say 90 minutes of combined duration. It's very important that we combine the ranges properly and don't simply add up the durations. This means we've made the decision that this area is probably a base and we're interested in keeping track of it.

Then, we look at the entire block radius, and mark everything in that range as being part of the same cluster. Only a core node can start a cluster, but once that's happened, normal non-core nodes can become members. If new hits occur in between two different clusters, they can be easily combined by setting one core node's parent to the other, making one big cluster. This is called a disjoint set data structure and it's very useful.

We implement path compression and unions by rank. The cluster retry scanner mentioned earlier takes advantage of this. We pick a random cluster really, a random core node with no parent, which will be the root of a cluster , then pick a random chunk that's a member, then check that.

This allows us to recheck bases without being biased towards bases with a larger area: we pick the cluster at random equally. If we picked chunks at random equally, it would be biased towards bases with more chunks.

Something else that uses this data is the associator. Running one day behind real time so as to not mess with any of this, the associator looks at all tracks that ended at interesting locations not at spawn, not on the highway and were more than 3 minutes long.

For each one, it grabs all players that logged off between 6 seconds before and 1 second after. If there were more than 10 such players, it ignores since this was a server restart. Otherwise, it divides up 1 "association point" equally among all such players. Then, it looks at where the track ended. Over time, this builds up who logs off where. It actually works pretty well. Finally, the clusters are used by the slurper.

This is what clicks blocks one at a time to download entire bases. It starts by ingesting the firehose of all hits no matter if it's from a filter or a scanner in real time. These are added to a queue then processed by marking the whole render distance as recently loaded, but only if it's a member of a cluster. Then, four times a second, we pick the furthest chunk away from spawn that we haven't picked like this in the last half hour, that was also marked as recently loaded in the last 30 seconds, then we "seed" that chunk.

We do this by asking the world generator for the entire chunk then picking 4 random coordinates on the surface. We click the top block, and the air block above it. If we've slurped this chunk before, we also do the highest non-air block and the lowest air block in the same way this keeps underground bases and skybases with no connection to the ground up to date. We also click a few completely random blocks just in case there's a skybase or underground base, that'll get it eventually.

Whenever we got a response in the slurper of what a block actually is, we first check if the response was loaded or unloaded. Remember any of these checks can fail because the chunk simply isn't loaded. If that's the case, we add the check to our list of unloaded responses. If we ever get a hit at that chunk in the future by a scanner, filter, or this slurper , we will resend all the checks that got this unloaded response.

But assuming the common case where the chunk is loaded, first we check if this matches the vanilla worldgen, and we check if it matches a previous check here, if any. So, we're comparing the current response to vanilla and to the previous response if we got one. If it's different from the previous response, that means someone has modified blocks here since last time, so this is interesting. If this block has changed, maybe adjacent ones have too.

We do the same thing if it's different from world gen, but we don't force a renew. There is a system of "must be newer than", where the slurper can ask for a certain coordinate and also say that they want a response that's fresher than a given timestamp. If we have an older response saved in the database, it'll be discarded. If we have a newer response saved, we'll give it instead of actually asking 2b2t. The seeds are designed to catch additions to builds: changes in the highest or lowest Y coordinates in the build are common, maybe the tower is being built upwards, or the mine dug downwards.

The "brush" system will refresh all those locations once a difference is found. And if that isn't smart enough to catch the changes, the base "must be newer than" is set to three weeks, so once every 3 weeks we will essentially "forget" the base and reslurp it from scratch.

Within the meantime, we're just keeping up to date little areas every half hour that Might indicate a change. There are a bunch of complicated systems underlying the slurper that let it do its job properly. For example, I mentioned earlier that when a connection is dropped, its pending tasks are redistributed to other connections; naturally the same thing is done for block checks. Additionally, the database is checked as a cache for checks we've already done etc.

That's all standard stuff, the goal being to never ever waste a block check by sending two for the same location in quick succession, even if two different parts of the code asked at the same time. We have a very complicated priority upgrading system that runs the whole way through, from the slurper all the way to the bot minecraft instances on digitalocean.

This means that the immediate adjacent blocks are higher priority than the diagonals which are in turn higher priority than the corners. However, if one of the immediate adjacent checks comes back to us and it turns out to be a difference too, we do the same thing, except now we're resending the same check but higher priority.

The whole system is built to carry out this priority upgrade quickly and correctly, with the most important aspect being that we only do the upgraded check, and don't in any scenario leave the old low priority check to be run uselessly at a later time.

So that's how the slurper ended up with a table of over ten billion blocks, forming a record of the construction of just about every base.

The half million block wide view again:. Skip to content. Star Branches Tags. Could not load branches. Could not load tags. Latest commit. Git stats 24 commits.

Depixel is another double resolution texture pack that aims to stick close to Minecraft's original. It does take artistic license in places, like with that skeleton's slightly spookier face, but it does generally stay quite true to classic Minecraft.

Consider this just one step past the Faithful Pack on the vanilla-to-stylized scale. Bare Bones offers the answer to the question "do we really need leaves? It's full of flat colors without any extra shades wasted on silly things like the illusion of texture.

It's straightforward and to the point. At first glance, Vanilla Additions doesn't appear to change much, but the magic is in the details. This pack is designed to maintain the original look of Minecraft while adding smaller things that liven it up with more variety. More varied mods, textures that change depending on the biome, and more dynamic UI.

If you like how Minecraft looks already, this just makes it a bit better. If you want exceptionally-detailed textures for your 3D block worlds, some creators have made texture packs with resolutions of pixels or more.

These are the most realistic Minecraft texture packs around. Some HD texture packs require using Optifine and most recommend using a shader pack for ultimate beautification. You can pick your favorite from our list of best Minecraft shaders. There are a lot of work-in-progress HD texture packs out there, some of which you'll have to pay to get the complete versions of.

We've included the best free options here for you, but if you're dedicated to the HD life, you may also want to keep an eye on Stratum and Realistico. To get access to the high-end packs you'll need to sign up to the team's Patreon, you can download the 32x pack as a taster and then sign up for higher resolutions. LBPR may be the best all-around HD texture pack choice thanks to the years of work and history from various artists that it's been built on. Animals, villagers, ores, trees, and terrain are all represented in high resolution textures with some stylistic choices that deviate from the vanilla look.

Don't worry, this texture pack doesn't actually require an RTX-capable graphics card. It's been converted to Java edition by Arkadya. This isn't a full texture set, only including some bricks, concrete, planks, and a few other blocks.

You probably won't be playing in survival with it on, but it's neat to use for screenshots! Herkenburg isn't an HD texture pack, using the same resolution as Minecraft's default textures, but it's definitely realistic.

Harkenburg doesn't just have nice modern looking bricks and ladders, it also turns other Minecraft blocks into modern objects. The furnace becomes a kitchen stove, the anvil a toilet, and various types of coral are traffic cones and fire hydrants.

It doesn't make much sense in survival mode, but it's a great pack for working on a modern day city build if you're a creative mode person. Minecraft PvP texture packs are a bit different from the usual resource packs.

Unlike other visual overhauls that prioritize a certain look, a PvP texture pack has different goals. Many PvP packs will be lower resolution to make sure your performance and FPS stay as high as possible. You'll also find that PvP texture packs focus on reticles that are easy to see, making swords smaller so they don't block as much of your view, and helping distinguish between ore blocks better. Version: Unlisted Resolution: 16x16 Download. TimeDeo 2k is an old community favorite PvP texture pack.

It now has a revamped version created by Finlay, too. TimeDeo 2k has very high contrast colors, meaning you won't have any trouble distinguishing between armors, weapons, and different ores at a glance. Its open style reticle is easy to spot at the center of your screen for games that require a lot of bow shooting. Bombies 80k is the latest pack from another frequent PvP texture pack maker, Tory.



0コメント

  • 1000 / 1000