7 Commits

Author SHA1 Message Date
Hykilpikonna c8875b2d75 [O] Optimize user report and usability for 1.14.4 2020-02-21 11:36:57 -05:00
Hykilpikonna 56d8d47289 Revert "Revert "Whatever""
This reverts commit 6c0760ae01.
2020-02-20 10:47:38 -05:00
Hykilpikonna 6c0760ae01 Revert "Whatever"
This reverts commit 4e28f711ed.
2020-02-20 10:42:38 -05:00
Hykilpikonna 8db7d96727 Revert "Merge remote-tracking branch 'origin/master'"
This reverts commit 3f57818c35, reversing
changes made to 4e28f711ed.
2020-02-20 10:42:03 -05:00
Neil 3f57818c35 Merge remote-tracking branch 'origin/master' 2020-02-18 16:25:41 +01:00
Neil 4e28f711ed Whatever 2020-02-18 16:24:52 +01:00
KESSLER Erwan a5da8b83e8 linked log to in-game chat 2019-12-26 23:41:02 +01:00
99 changed files with 1317 additions and 2877 deletions
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 KaptainWutax
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1 -84
View File
@@ -1,84 +1 @@
# SeedCracker
## Installation
### Vanilla Launcher
Download and install the [fabric mod loader](https://fabricmc.net/use/).
### MultiMC
Add a new minecraft instance and press "Install Fabric" in the instance options.
Then download the lastest [release](https://github.com/KaptainWutax/SeedCracker/releases) of SeedCracker and put the `.jar` file in your mods directory, either `%appdata%/.minecraft/mods/` folder for the vanilla launcher or your own MultiMC instance folder.
## Usage
Run minecraft with the mod installed and run around in the world. Once the mod has collected enough data, it will start the cracking process automatically and output the seed in chat. For the process to start, you are required to locate atleast 5 combined struture and decorator features, 5 biomes and the end pillars.
### Supported Structures(from best to worst)
- Ocean Monument
- End City
- Buried Treasure
- Desert Pyramid
- Jungle Temple
- Swamp Hut
- Shipwreck
### Supported Decorators(from best to worst)
- Dungeon
- End Gateway
- Desert Well
- Emerald Ore
## Commands
The command prefix for this mod is /seed.
### Render Command
-`/seed render outlines <ON/OFF/XRAY>`
This command only affects the renderer feedback. The default value is 'XRAY' and highlights data through blocks. You can set the render mod to 'ON' for more standard rendering.
### Finder Command
-`/seed render finder type <FEATURE_TYPE> (ON/OFF)`
-`/seed finder category (BIOMES/ORES/OTHERS/STRUCTURES) (ON/OFF)`
This command is used to disable finders in case you are aware the data is wrong. For example, a map generated in 1.14 has different decorators and would require you to disable them while going through those chunks.
## Video Tutorial
https://youtu.be/1ChmLi9og8Q
## Upcoming Features
A list of features I have on my mind... they won't necessarily be implemented in this order if at all.
- SHA2 brute-forcing, auxiliary to biomes search.
- Dungeon floor cracker, fast lattice reversal.
- Stronghold portal room cracker. (alternative to dungeon floor?)
- Faster brute-forcing by reorganizing located features list.
- End and nether biome finders. (nether would mostly be in preparation for 1.16)
- Chest loot finders. (fun meme, hell to implement)
## Setting up the Workspace
-Clone the repository.
-Run `gradlew genSources <idea|eclipse>`.
## Building the Mod
-Update the version in `build.gradle` and `fabric.mod.json`.
-Run `gradlew build`.
## Contributors
[KaptainWutax](https://github.com/KaptainWutax) - Author
[neil](https://www.youtube.com/channel/UCbM3acUrR8Ku6pjgRUNPnbQ/featured) - Video Tutorial
[Nekzuris](https://github.com/Nekzuris) - README
SeedCracker
+5 -15
View File
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '0.2.6-SNAPSHOT'
id 'fabric-loom' version '0.2.5-SNAPSHOT'
id 'maven-publish'
}
@@ -12,27 +12,18 @@ group = project.maven_group
minecraft {
}
repositories {
maven {
name = "CottonMC"
url = "http://server.bbkr.space:8081/artifactory/libs-release"
}
}
dependencies {
//to change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}"
modCompile "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
//modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
// You may need to force-disable transitiveness on them.
modImplementation "io.github.cottonmc:LibGui:1.6.0"
include "io.github.cottonmc:LibGui:1.6.0"
modImplementation("net.fabricmc.fabric-api:fabric-api:${project.fabric_version}")
include("net.fabricmc.fabric-api:fabric-api:${project.fabric_version}")
}
processResources {
@@ -65,15 +56,14 @@ task sourcesJar(type: Jar, dependsOn: classes) {
jar {
from "LICENSE"
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
+5 -6
View File
@@ -3,16 +3,15 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.15.2
yarn_mappings=1.15.2+build.8
loader_version=0.7.6+build.180
minecraft_version=1.14.4
yarn_mappings=1.14.4+build.15
loader_version=0.7.2+build.174
# Mod Properties
mod_version = 0.0.2-alpha
mod_version = 1.0.0
maven_group = kaptainwutax
archives_base_name = seedcracker
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.4.32+build.292-1.15
modmenu_version=1.10.1+build.30
fabric_version=0.4.1+build.245-1.14
@@ -1,220 +1,359 @@
package kaptainwutax.seedcracker;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import kaptainwutax.seedcracker.cracker.*;
import kaptainwutax.seedcracker.cracker.population.PopulationData;
import kaptainwutax.seedcracker.finder.FinderQueue;
import kaptainwutax.seedcracker.gui.GuiItem;
import kaptainwutax.seedcracker.render.RenderQueue;
import kaptainwutax.seedcracker.util.Log;
import kaptainwutax.seedcracker.util.Rand;
import net.fabricmc.api.ModInitializer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.util.Identifier;
import net.minecraft.util.Rarity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.MutableIntBoundingBox;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.biome.layer.BiomeLayerSampler;
import net.minecraft.world.biome.layer.BiomeLayers;
import net.minecraft.world.biome.source.BiomeSourceType;
import net.minecraft.world.gen.ChunkRandom;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.StrongholdFeature;
import net.minecraft.world.level.LevelGeneratorType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class SeedCracker implements ModInitializer {
private static final SeedCracker INSTANCE = new SeedCracker();
private DataStorage dataStorage = new DataStorage();
public static Item GUI_ITEM=new GuiItem(new Item.Settings().group(ItemGroup.MISC).rarity(Rarity.EPIC));
@Override
public List<Long> worldSeeds = null;
public List<Long> structureSeeds = null;
public List<Integer> pillarSeeds = null;
private TimeMachine timeMachine = new TimeMachine();
private List<StructureData> structureCache = new ArrayList<>();
private List<PopulationData> populationCache = new ArrayList<>();
private List<BiomeData> biomeCache = new ArrayList<>();
@Override
public void onInitialize() {
RenderQueue.get().add("hand", FinderQueue.get()::renderFinders);
Registry.register(Registry.ITEM,new Identifier("seedcracker","gui_item"),GUI_ITEM);
DecoratorCache.get().initialize();
/*
long ss = 5718603440394L;
LCG lcg = Rand.JAVA_LCG.combine(-5);
System.out.println("FETCHING SEEDS============");
long structureSeed = 29131954246896L;
ChunkPos chunkPos = new ChunkPos(117, 23);
for(int i = 0; i < 8; i++) {
System.out.println("n");
PopulationReversal.getWorldSeeds(ss, 31 * 16, 19 * 16).forEach(seed -> {
System.out.println("Structure seed: " + seed);
for(long j = 0; j < (1L << 16); j++) {
long worldSeed = (j << 48) | structureSeed;
for(int u = 0; u < 1 << 16; u++) {
long worldSeed = ((long)u << 48) | seed;
if(RandomSeed.isRandomSeed(worldSeed)) {
System.out.println("nextLong() equivalent: " + worldSeed);
}
}
});
ss = lcg.nextSeed(ss);
}*/
if(initialize(worldSeed).contains(chunkPos)) {
System.out.println(worldSeed);
this.checkWorldSeed(worldSeed, chunkPos);
}
}
System.out.println("FETCHING SEEDS============");
*/
/*
System.out.println(9348141881871L ^ Rand.JAVA_LCG.multiplier);
DungeonData data = new DungeonData(new ChunkPos(18, 8), Biomes.JUNGLE, new ArrayList<>(), new ArrayList<>());
data.test(-2418316773073950375L);
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(new File("all_mineral.txt")));
BufferedWriter writer = new BufferedWriter(new FileWriter("kaktoos14.txt"));
StructureData t = new StructureData(new ChunkPos(0, 0), StructureFeatures.BURIED_TREASURE);
StructureData s = new StructureData(new ChunkPos(0, 0), StructureFeatures.SHIPWRECK);
StructureData v = new StructureData(new ChunkPos(1, 1), StructureFeatures.VILLAGE);
for(int i = 0; i < (1 << 16); i++) {
long worldSeed = 9368770777595L | ((long)i << 48);
BiomeData b1 = new BiomeData(new BlockPos(9, 0, 9), biome -> biome.hasStructureFeature(Feature.BURIED_TREASURE));
BiomeData b2 = new BiomeData(new BlockPos(9, 0, 9), biome -> biome.hasStructureFeature(Feature.SHIPWRECK));
BiomeData b3 = new BiomeData(new BlockPos(9 + 16, 0, 9 + 16), biome -> biome.hasStructureFeature(Feature.VILLAGE));
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
SpawnPointData spawn = new SpawnPointData(BlockPos.ORIGIN, 50);
ChestLootData loot = new ChestLootData(
MCLootTables.BURIED_TREASURE_CHEST,
new ChestLootData.Stack(Items.EMERALD, Predicates.MORE_OR_EQUAL_TO, 3),
new ChestLootData.Stack(Items.IRON_INGOT, Predicates.MORE_OR_EQUAL_TO, 4),
new ChestLootData.Stack(Items.GOLD_INGOT, Predicates.MORE_OR_EQUAL_TO, 3),
new ChestLootData.Stack(Items.TNT, Predicates.MORE_OR_EQUAL_TO, 1),
new ChestLootData.Stack(Items.DIAMOND, Predicates.MORE_OR_EQUAL_TO, 1)
);
int count = 0;
Rand rand = new Rand(0L, false);
for(long seed = (1L << 48) - 1; seed >= 0; seed--) {
if(!t.test(seed, rand))continue;
if(!s.test(seed, rand))continue;
if(!v.test(seed, rand))continue;
if(!loot.test(seed + 20002L, rand))continue;
for(long u = 0L; u < 1L << 16; u++) {
long worldSeed = (u << 48) | seed;
FakeBiomeSource source = new FakeBiomeSource(worldSeed);
if(!b1.test(source))continue;
if(!b2.test(source))continue;
if(!b3.test(source))continue;
if(!spawn.test(source))continue;
String s2 = "[" + (++count) + "] " + worldSeed + " with structure seed " + seed + "\n";
System.out.print(s2);
writer.write(s2);
writer.flush();
break;
if(sampler.sample(8, 8) == Biomes.DESERT) {
writer.write(worldSeed + "\n");
}
}
} catch(Exception e) {
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}*/
}
/*
long seed = 1_000_000_000_000_000L;
int distance = 80;
Predicate<Biome>[] trees = new Predicate[] {
biome -> biome instanceof ForestBiome || biome instanceof WoodedHillsBiome, //OAK TREE
biome -> biome instanceof SavannaBiome || biome instanceof SavannaPlateauBiome, //ACACIA TREE
biome -> biome instanceof DarkForestHillsBiome || biome instanceof DarkForestBiome, //DARK OAK TREE
biome -> biome instanceof SnowyTaigaBiome || biome instanceof TaigaBiome, //SPRUCE TREE
biome -> biome instanceof JungleBiome || biome instanceof JungleHillsBiome || biome instanceof ModifiedJungleBiome, //JUNGLE TREE
};
Set<Integer> ids = new HashSet<>();
do {
FakeBiomeSource source = new FakeBiomeSource(seed);
BlockPos spawn = SpawnPointData.getSpawnPoint(source);
int x = spawn.getX();
int z = spawn.getZ();
//X direction
for(int s = -1; s != 1; s = 1) {
for(int d = 0; d < distance; d++) {
Biome biome = BiomeData.sampleBiome(source, x + s * d, 0, z);
for(int j = 0; j < trees.length; j++) {
if(!ids.contains(j) && trees[j].test(biome)) {
ids.add(j);
}
}
}
if(ids.size() >= trees.length - 1) {
System.out.println(seed + ", " + ids);
ids.clear();
break;
}
ids.clear();
//Z direction
for(int d = 0; d < distance; d++) {
Biome biome = BiomeData.sampleBiome(source, x, 0, z + s * d);
for(int j = 0; j < trees.length; j++) {
if(!ids.contains(j) && trees[j].test(biome)) {
ids.add(j);
}
}
}
if(ids.size() >= trees.length - 1) {
System.out.println(seed + ", " + ids);
ids.clear();
break;
}
ids.clear();
}
seed++;
} while(seed != 0L);*/
/*
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(new File("season_7_seeds_negative.txt")));
int count = 0;
long seed = 0L;
BiomeData m1 = new BiomeData(new BlockPos(-200, 0, 0), biome -> biome instanceof MushroomFieldsBiome || biome instanceof MushroomFieldShoreBiome);
BiomeData m2 = new BiomeData(new BlockPos(200, 0, 0), biome -> biome instanceof MushroomFieldsBiome || biome instanceof MushroomFieldShoreBiome);
BiomeData m3 = new BiomeData(new BlockPos(0, 0, -200), biome -> biome instanceof MushroomFieldsBiome || biome instanceof MushroomFieldShoreBiome);
BiomeData m4 = new BiomeData(new BlockPos(0, 0, 200), biome -> biome instanceof MushroomFieldsBiome || biome instanceof MushroomFieldShoreBiome);
do {
FakeBiomeSource source = new FakeBiomeSource(seed);
if(m1.test(source) && m2.test(source) && m3.test(source) && m4.test(source)) {
String s = "[" + (++count) + "] " + seed + "\n";
System.out.println(s);
writer.write(s);
writer.flush();
}
seed--;
} while(seed != 0L);
writer.close();
} catch(Exception e) {
;
}*/
/*
long popSeed = 107038380818082L;
for(int x = 0; x < 10000; x++) {
StructureData b = new StructureData(new ChunkPos(x, 0), StructureFeatures.BURIED_TREASURE);
BiomeData b1 = new BiomeData(new BlockPos(16 * x + 9, 0, 9), Biomes.BEACH);
List<Long> worldSeeds = Magic.getSeedFromChunkseed(popSeed, x * 16, 0);
int finalX = x;
worldSeeds.forEach(structureSeed -> {
if(b.test(structureSeed, new Rand(0L))) {
System.out.println("structure seed " + structureSeed + " at x " + (finalX * 16));
for(long u = 0L; u < 1L << 16; u++) {
long worldSeed = (u << 48) | structureSeed;
FakeBiomeSource source = new FakeBiomeSource(worldSeed);
if(!b1.test(source))continue;
System.out.println(worldSeed + " with structure seed " + structureSeed + " at x " + (finalX * 16));
}
}
});
}*/
private void checkWorldSeed(long worldSeed, ChunkPos pos) {
StrongholdFeature.Start start = new StrongholdFeature.Start(Feature.STRONGHOLD, pos.x, pos.z, Biomes.PLAINS, MutableIntBoundingBox.empty(), 0, worldSeed);
}
public static SeedCracker get() {
return INSTANCE;
}
public DataStorage getDataStorage() {
return this.dataStorage;
public void clear() {
this.worldSeeds = null;
this.structureSeeds = null;
this.pillarSeeds = null;
this.structureCache.clear();
this.biomeCache.clear();
this.populationCache.clear();
}
public synchronized boolean onPillarData(PillarData pillarData) {
if(pillarData != null && (this.pillarSeeds == null || this.pillarSeeds.isEmpty())) {
Log.warn("Looking for pillar seeds...");
this.pillarSeeds = pillarData.getPillarSeeds();
if(this.pillarSeeds.size() > 0) {
Log.warn("Finished search with " + this.pillarSeeds);
} else {
Log.error("Finished search with no seeds.");
}
this.onStructureData(null);
return true;
}
return false;
}
public synchronized boolean onStructureData(StructureData structureData) {
boolean added = false;
if(structureData != null && !this.structureCache.contains(structureData)) {
this.structureCache.add(structureData);
added = true;
Log.warn("Structure added: " + structureData);
System.out.println(new Gson().toJson(structureCache));
}
if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() + this.populationCache.size() >= 6) {
this.structureSeeds = new ArrayList<>();
Log.warn("Looking for structure seeds with " + this.structureCache.size() + " structure features.");
Log.warn("Looking for structure seeds with " + this.populationCache.size() + " population features.");
this.pillarSeeds.forEach(pillarSeed -> {
timeMachine.buildStructureSeeds(pillarSeed, this.structureCache, this.populationCache, this.structureSeeds);
});
if(this.structureSeeds.size() > 0) {
Log.warn("Finished search with " + this.structureSeeds);
} else {
Log.error("Finished search with no seeds.");
}
//this.structureCache.clear();
//this.onPopulationData(null);
this.onBiomeData(null);
} else if(this.structureSeeds != null && structureData != null) {
this.structureSeeds.removeIf(structureSeed -> {
ChunkRandom chunkRandom = new ChunkRandom();
chunkRandom.setStructureSeed(structureSeed, structureData.getRegionX(), structureData.getRegionZ(), structureData.getSalt());
return !structureData.test(chunkRandom);
});
this.onBiomeData(null);
}
return added;
}
public synchronized boolean onPopulationData(PopulationData populationData) {
boolean added = false;
if(populationData != null && !this.populationCache.contains(populationData)) {
this.populationCache.add(populationData);
added = true;
}
this.onStructureData(null);
return added;
}
public synchronized boolean onBiomeData(BiomeData biomeData) {
boolean added = false;
if(biomeData != null && !this.biomeCache.contains(biomeData)) {
this.biomeCache.add(biomeData);
added = true;
Log.warn("Biome added: " + biomeData);
System.out.println(new Gson().toJson(biomeCache));
}
if(this.worldSeeds == null && this.structureSeeds != null && this.biomeCache.size() >= 5) {
this.worldSeeds = new ArrayList<>();
Log.warn("Looking for world seeds with " + this.biomeCache.size() + " biomes.");
for(int i = 0; i < this.structureSeeds.size(); i++) {
Log.warn("Progress " + (i * 100.0f) / this.structureSeeds.size() + "%...");
long structureSeed = this.structureSeeds.get(i);
for (long j = 0; j < (1L << 16); j++) {
long worldSeed = (j << 48) | structureSeed;
boolean goodSeed = true;
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
for(BiomeData data : this.biomeCache) {
if (!data.test(worldSeed, sampler)) {
goodSeed = false;
break;
}
}
if(goodSeed) {
this.worldSeeds.add(worldSeed);
}
}
}
if(this.worldSeeds.size() > 0) {
Log.warn("Finished search with " + this.worldSeeds + (this.worldSeeds.size() == 1 ? " seed." : " seeds."));
} else {
Log.error("Finished search with no seeds.");
}
} else if(this.worldSeeds != null && biomeData != null) {
this.worldSeeds.removeIf(worldSeed -> {
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
return !biomeData.test(worldSeed, sampler);
});
} else if(this.worldSeeds != null) {
this.worldSeeds.removeIf(worldSeed -> {
for(BiomeData data: this.biomeCache) {
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
if(!biomeData.test(worldSeed, sampler))return true;
}
return false;
});
}
return added;
}
public static void main(String[] args) throws Exception {
for(int i = 0; i < 10000; i++) {
Rand rand = new Rand(i, false);
if(rand.nextInt(700) == 0)System.out.println(i);
}
/*Random rand = new Random(1234L);
IntStream.range(0, 8).mapToObj((int_1x) -> {
int int_2 = rand.nextInt(16);
int int_3 = rand.nextInt(256);
int int_4 = rand.nextInt(16);
System.out.println("Created " + int_2 + ", " + int_3 + ", " + int_4);
return new BlockPos(int_2, int_3, int_4);
}).forEach(pos -> {
System.out.println("Populating " + pos);
});*/
/*
System.out.println(validSeed(65867021031296932L));
BufferedReader reader = new BufferedReader(new FileReader("run/seeds.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("run/kaktoos14.txt"));
while(reader.ready()) {
long seed = Long.parseLong(reader.readLine().split(Pattern.quote(" "))[0]);
seed ^= Rand.JAVA_LCG.multiplier;
seed -= 60007;
writer.write(seed + "===========================================\n");
for(int i = 0; i < (1 << 16); i++) {
long worldSeed = seed | ((long)i << 48);
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
if(sampler.sample(8, 8) == Biomes.DESERT) {
writer.write(worldSeed + "\n");
}
}
writer.flush();
}
writer.close();*/
}
private static List<ChunkPos> initialize(long worldSeed) {
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[0];
List<ChunkPos> startPositions = new ArrayList<>();
List<Biome> validBiomes = Lists.newArrayList();
Iterator biomeIterator = Registry.BIOME.iterator();
while(biomeIterator.hasNext()) {
Biome biome = (Biome)biomeIterator.next();
if(biome != null && biome.hasStructureFeature(Feature.STRONGHOLD)) {
validBiomes.add(biome);
}
}
Random rand = new Random(worldSeed);
double randomRadian = rand.nextDouble() * Math.PI * 2.0D;
//Actually 128, but we don't care about all of them.
for(int i = 0; i < 3; ++i) {
double double_2 = 128.0D + (rand.nextDouble() - 0.5D) * 80.0D;
int x = (int)Math.round(Math.cos(randomRadian) * double_2);
int z = (int)Math.round(Math.sin(randomRadian) * double_2);
BlockPos locatedPos = locateBiome(sampler, (x << 4) + 8, (z << 4) + 8, 112, validBiomes, rand);
if(locatedPos != null) {
x = locatedPos.getX() >> 4;
z = locatedPos.getZ() >> 4;
}
startPositions.add(new ChunkPos(x, z));
randomRadian += (Math.PI * 2.0D) / 3.0d;
}
return startPositions;
}
public static BlockPos locateBiome(BiomeLayerSampler sampler, int x, int z, int size, List<Biome> validBiomes, Random rand) {
int int_4 = x - size >> 2;
int int_5 = z - size >> 2;
int int_6 = x + size >> 2;
int int_7 = z + size >> 2;
int int_8 = int_6 - int_4 + 1;
int int_9 = int_7 - int_5 + 1;
Biome[] biomeSample = sampler.sample(int_4, int_5, int_8, int_9);
BlockPos pos = null;
int int_10 = 0;
for(int i = 0; i < int_8 * int_9; ++i) {
int int_12 = int_4 + i % int_8 << 2;
int int_13 = int_5 + i / int_8 << 2;
if (validBiomes.contains(biomeSample[i])) {
if(pos == null || rand.nextInt(int_10 + 1) == 0) {
pos = new BlockPos(int_12, 0, int_13);
}
++int_10;
}
}
return pos;
}
}
@@ -2,7 +2,6 @@ package kaptainwutax.seedcracker.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import kaptainwutax.seedcracker.init.ClientCommands;
import net.minecraft.client.MinecraftClient;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.LiteralText;
@@ -16,8 +15,8 @@ public abstract class ClientCommand {
public abstract void build(LiteralArgumentBuilder<ServerCommandSource> builder);
protected final void sendFeedback(String message, Formatting color, boolean overlay) {
MinecraftClient.getInstance().player.addChatMessage(new LiteralText(message).formatted(color), overlay);
protected final void sendFeedback(String message, boolean overlay) {
MinecraftClient.getInstance().player.addChatMessage(new LiteralText(message).formatted(Formatting.AQUA), overlay);
}
public final void register(CommandDispatcher<ServerCommandSource> dispatcher) {
@@ -1,12 +1,8 @@
package kaptainwutax.seedcracker.init;
package kaptainwutax.seedcracker.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import kaptainwutax.seedcracker.command.ClientCommand;
import kaptainwutax.seedcracker.command.FinderCommand;
import kaptainwutax.seedcracker.command.GuiCommand;
import kaptainwutax.seedcracker.command.RenderCommand;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.command.CommandException;
@@ -24,12 +20,10 @@ public class ClientCommands {
public static RenderCommand RENDER;
public static FinderCommand FINDER;
public static GuiCommand GUI;
static {
COMMANDS.add(RENDER = new RenderCommand());
COMMANDS.add(FINDER = new FinderCommand());
COMMANDS.add(GUI = new GuiCommand());
}
public static void registerCommands(CommandDispatcher<ServerCommandSource> dispatcher) {
@@ -1,10 +1,9 @@
package kaptainwutax.seedcracker.command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.finder.FinderConfig;
import kaptainwutax.seedcracker.finder.FinderQueue;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.Formatting;
import static net.minecraft.server.command.CommandManager.literal;
@@ -17,7 +16,7 @@ public class FinderCommand extends ClientCommand {
@Override
public void build(LiteralArgumentBuilder<ServerCommandSource> builder) {
for(Finder.Type finderType: Finder.Type.values()) {
for(FinderConfig.Type finderType: FinderConfig.Type.values()) {
builder.then(literal("type")
.executes(context -> this.printFinderType(finderType))
.then(literal(finderType.toString())
@@ -26,7 +25,7 @@ public class FinderCommand extends ClientCommand {
);
}
for(Finder.Category finderCategory: Finder.Category.values()) {
for(FinderConfig.Category finderCategory: FinderConfig.Category.values()) {
builder.then(literal("category")
.executes(context -> this.printFinderCategory(finderCategory))
.then(literal(finderCategory.toString())
@@ -36,28 +35,24 @@ public class FinderCommand extends ClientCommand {
}
}
private int printFinderCategory(Finder.Category finderCategory) {
Finder.Type.getForCategory(finderCategory).forEach(this::printFinderType);
private int printFinderCategory(FinderConfig.Category finderCategory) {
FinderConfig.Type.getForCategory(finderCategory).forEach(this::printFinderType);
return 0;
}
private int printFinderType(Finder.Type finderType) {
this.sendFeedback("Finder " + finderType + " is set to [" + String.valueOf(FinderQueue.get().finderProfile.getTypeState(finderType)).toUpperCase() + "].", Formatting.AQUA,false);
private int printFinderType(FinderConfig.Type finderType) {
this.sendFeedback("Finder " + finderType + " is set to [" + String.valueOf(FinderQueue.get().finderConfig.getTypeState(finderType)).toUpperCase() + "].", false);
return 0;
}
private int setFinderCategory(Finder.Category finderCategory, boolean flag) {
Finder.Type.getForCategory(finderCategory).forEach(finderType -> this.setFinderType(finderType, flag));
private int setFinderCategory(FinderConfig.Category finderCategory, boolean flag) {
FinderConfig.Type.getForCategory(finderCategory).forEach(finderType -> this.setFinderType(finderType, flag));
return 0;
}
private int setFinderType(Finder.Type finderType, boolean flag) {
if(FinderQueue.get().finderProfile.setTypeState(finderType, flag)) {
this.sendFeedback("Finder " + finderType + " has been set to [" + String.valueOf(flag).toUpperCase() + "].", Formatting.AQUA, false);
} else {
this.sendFeedback("Your current finder profile is locked and cannot be modified. Please make a copy first.", Formatting.RED, false);
}
private int setFinderType(FinderConfig.Type finderType, boolean flag) {
FinderQueue.get().finderConfig.setTypeState(finderType, flag);
this.sendFeedback("Finder " + finderType + " has been set to [" + String.valueOf(flag).toUpperCase() + "].", false);
return 0;
}
@@ -1,42 +0,0 @@
package kaptainwutax.seedcracker.command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.finder.FinderQueue;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting;
import static kaptainwutax.seedcracker.SeedCracker.GUI_ITEM;
import static net.minecraft.server.command.CommandManager.literal;
public class GuiCommand extends ClientCommand {
@Override
public String getName() {
return "gui";
}
@Override
public void build(LiteralArgumentBuilder<ServerCommandSource> builder) {
builder.executes(ctx->
{
ServerCommandSource source = ctx.getSource();
ClientPlayerEntity self =(ClientPlayerEntity) source.getEntity();
assert self != null;
if(!self.inventory.insertStack(new ItemStack(GUI_ITEM))){
throw new SimpleCommandExceptionType(new TranslatableText("inventory.isfull")).create();
}
return 1;
});
}
}
@@ -3,7 +3,6 @@ package kaptainwutax.seedcracker.command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import kaptainwutax.seedcracker.finder.FinderQueue;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.Formatting;
import static net.minecraft.server.command.CommandManager.literal;
@@ -28,13 +27,13 @@ public class RenderCommand extends ClientCommand {
}
private int printRenderMode() {
this.sendFeedback("Current render mode is set to [" + FinderQueue.get().renderType + "].", Formatting.AQUA, false);
this.sendFeedback("Current render mode is set to [" + FinderQueue.get().renderType + "].", false);
return 0;
}
private int setRenderMode(FinderQueue.RenderType renderType) {
FinderQueue.get().renderType = renderType;
this.sendFeedback("Set render mode to [" + FinderQueue.get().renderType + "].", Formatting.AQUA, false);
this.sendFeedback("Set render mode to [" + FinderQueue.get().renderType + "].", false);
return 0;
}
@@ -1,61 +1,32 @@
package kaptainwutax.seedcracker.cracker;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.ISeedStorage;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.VoronoiBiomeAccessType;
import net.minecraft.world.biome.layer.BiomeLayerSampler;
import java.util.function.Predicate;
public class BiomeData implements ISeedStorage {
private BlockPos pos;
public class BiomeData {
private int x;
private int z;
private Biome biome;
private Predicate<Biome> biomePredicate;
public BiomeData(BlockPos pos, Biome biome) {
this.pos = pos;
public BiomeData(int x, int z, Biome biome) {
this.x = x;
this.z = z;
this.biome = biome;
}
public BiomeData(BlockPos pos, int biomeId) {
this.pos = pos;
this.biome = Registry.BIOME.get(biomeId);
public BiomeData(int x, int z, String biomeId) {
this(x, z, Registry.BIOME.get(new Identifier(biomeId)));
}
public BiomeData(BlockPos pos, Predicate<Biome> biomePredicate) {
this.pos = pos;
this.biomePredicate = biomePredicate;
public BiomeData(int x, int z, int biomeId) {
this(x, z, Registry.BIOME.get(biomeId));
}
public boolean test(FakeBiomeSource source) {
if(this.biome == null) {
return this.biomePredicate.test(sampleBiome(source, this.pos.getX(), this.pos.getY(), this.pos.getZ()));
}
return sampleBiome(source, this.pos.getX(), this.pos.getY(), this.pos.getZ()) == this.biome;
}
public BlockPos getPos() {
return this.pos;
}
public Biome getBiome() {
return this.biome;
}
public static Biome sampleBiome(FakeBiomeSource source, int x, int y, int z) {
return VoronoiBiomeAccessType.INSTANCE.getBiome(source.getHashedSeed(), x, y, z, source);
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.BIOMES);
public boolean test(long worldSeed, BiomeLayerSampler sampler) {
return sampler.sample(this.x, this.z) == this.biome;
}
@Override
@@ -69,12 +40,4 @@ public class BiomeData implements ISeedStorage {
return false;
}
@Override
public int hashCode() {
if(this.biomePredicate == null) {
return this.biome.getName().asFormattedString().hashCode();
}
return super.hashCode();
}
}
@@ -1,95 +0,0 @@
package kaptainwutax.seedcracker.cracker;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.loot.LootBuilder;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.context.LootContext;
import net.minecraft.loot.context.LootContextParameters;
import net.minecraft.loot.context.LootContextTypes;
import net.minecraft.util.math.BlockPos;
import java.util.*;
import java.util.function.BiPredicate;
public class ChestLootData {
private LootTable lootTable;
private Map<Item, List<Stack>> stacksMap = new HashMap<>();
public ChestLootData(LootTable lootTable, Stack... stacks) {
this.lootTable = lootTable;
for(Stack stack: stacks) {
Item item = stack.item;
if(!this.stacksMap.containsKey(item)) {
this.stacksMap.put(item, new ArrayList<>());
}
this.stacksMap.get(item).add(stack);
}
}
public boolean test(long lootSeed, Rand rand) {
rand.setSeed(lootSeed, true);
LootContext lootContext = new LootBuilder().setRandom(rand.toRandom())
.put(LootContextParameters.POSITION, new BlockPos(0, 0, 0)).build(LootContextTypes.CHEST);
List<ItemStack> itemStacks = this.lootTable.getDrops(lootContext);
Map<Item, Integer> lootItems = new HashMap<>();
itemStacks.forEach(itemStack -> {
lootItems.put(itemStack.getItem(), lootItems.getOrDefault(itemStack.getItem(), 0) + itemStack.getCount());
});
Set<Item> foundItems = new HashSet<>();
for(Map.Entry<Item, Integer> lootItem: lootItems.entrySet()) {
Item item = lootItem.getKey();
List<Stack> stacks = this.stacksMap.get(item);
if(stacks == null)continue;
boolean matches = true;
for(Stack stack: stacks) {
if(!stack.test(lootItem.getValue())) {
matches = false;
break;
}
}
if(matches) {
foundItems.add(item);
}
}
return foundItems.size() == this.stacksMap.size();
}
public static class Stack {
private Item item;
private BiPredicate<Integer, Integer> predicate;
private int amount;
public Stack(Item item, BiPredicate<Integer, Integer> predicate, int amount) {
this.item = item;
this.predicate = predicate;
this.amount = amount;
}
public boolean test(int count) {
return this.predicate.test(count, this.amount);
}
@Override
public int hashCode() {
return item.hashCode() * 31 + this.amount;
}
}
}
@@ -0,0 +1,69 @@
package kaptainwutax.seedcracker.cracker;
import kaptainwutax.seedcracker.util.Log;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.DecoratedFeatureConfig;
import net.minecraft.world.gen.feature.FeatureConfig;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DecoratorCache {
public static int INVALID = -1;
private static DecoratorCache INSTANCE = new DecoratorCache();
private boolean initialized = false;
private Map<Biome, Map<Decorator<?>, Integer>> decoratorSaltMap = new HashMap<>();
public static DecoratorCache get() {
return INSTANCE;
}
public void initialize() {
Registry.BIOME.forEach(biome -> {
this.decoratorSaltMap.put(biome, new HashMap<>());
for(GenerationStep.Feature genStep: GenerationStep.Feature.values()) {
this.initializeBiomeStep(biome, genStep);
}
});
this.initialized = true;
}
private void initializeBiomeStep(Biome biome, GenerationStep.Feature genStep) {
List<ConfiguredFeature<?>> features = biome.getFeaturesForStep(genStep);
for(int i = 0; i < features.size(); i++) {
FeatureConfig config = features.get(i).config;
if(!(config instanceof DecoratedFeatureConfig))continue;
this.decoratorSaltMap.get(biome).put(((DecoratedFeatureConfig)config).decorator.decorator, i + genStep.ordinal() * 10000);
}
}
public int getSalt(Biome biome, Decorator<?> feature, boolean debug) {
if(!this.initialized) {
this.initialize();
}
Integer salt = this.decoratorSaltMap.get(biome).get(feature);
if(salt == null) {
if(debug) {
Log.error(biome.getClass().getSimpleName() + " does not have decorator " + feature + ".");
}
salt = INVALID;
}
return salt;
}
}
@@ -1,49 +0,0 @@
package kaptainwutax.seedcracker.cracker;
import com.google.common.collect.ImmutableSet;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.biome.layer.BiomeLayers;
import net.minecraft.world.biome.source.BiomeLayerSampler;
import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.gen.chunk.OverworldChunkGeneratorConfig;
import net.minecraft.world.level.LevelGeneratorType;
import net.minecraft.world.level.LevelProperties;
import java.util.Set;
public class FakeBiomeSource extends BiomeSource {
public static final OverworldChunkGeneratorConfig CHUNK_GEN_CONFIG = new OverworldChunkGeneratorConfig();
private static final Set<Biome> BIOMES;
private final BiomeLayerSampler biomeSampler;
private long seed;
private long hashedSeed;
public FakeBiomeSource(long worldSeed) {
super(BIOMES);
this.seed = worldSeed;
this.hashedSeed = LevelProperties.sha256Hash(worldSeed);
this.biomeSampler = BiomeLayers.build(this.seed, LevelGeneratorType.DEFAULT, CHUNK_GEN_CONFIG);
}
@Override
public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) {
return this.biomeSampler.sample(biomeX, biomeZ);
}
public long getSeed() {
return this.seed;
}
public long getHashedSeed() {
return this.hashedSeed;
}
static {
BIOMES = ImmutableSet.of(Biomes.OCEAN, Biomes.PLAINS, Biomes.DESERT, Biomes.MOUNTAINS, Biomes.FOREST, Biomes.TAIGA, new Biome[]{Biomes.SWAMP, Biomes.RIVER, Biomes.FROZEN_OCEAN, Biomes.FROZEN_RIVER, Biomes.SNOWY_TUNDRA, Biomes.SNOWY_MOUNTAINS, Biomes.MUSHROOM_FIELDS, Biomes.MUSHROOM_FIELD_SHORE, Biomes.BEACH, Biomes.DESERT_HILLS, Biomes.WOODED_HILLS, Biomes.TAIGA_HILLS, Biomes.MOUNTAIN_EDGE, Biomes.JUNGLE, Biomes.JUNGLE_HILLS, Biomes.JUNGLE_EDGE, Biomes.DEEP_OCEAN, Biomes.STONE_SHORE, Biomes.SNOWY_BEACH, Biomes.BIRCH_FOREST, Biomes.BIRCH_FOREST_HILLS, Biomes.DARK_FOREST, Biomes.SNOWY_TAIGA, Biomes.SNOWY_TAIGA_HILLS, Biomes.GIANT_TREE_TAIGA, Biomes.GIANT_TREE_TAIGA_HILLS, Biomes.WOODED_MOUNTAINS, Biomes.SAVANNA, Biomes.SAVANNA_PLATEAU, Biomes.BADLANDS, Biomes.WOODED_BADLANDS_PLATEAU, Biomes.BADLANDS_PLATEAU, Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.COLD_OCEAN, Biomes.DEEP_WARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN, Biomes.DEEP_COLD_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.SUNFLOWER_PLAINS, Biomes.DESERT_LAKES, Biomes.GRAVELLY_MOUNTAINS, Biomes.FLOWER_FOREST, Biomes.TAIGA_MOUNTAINS, Biomes.SWAMP_HILLS, Biomes.ICE_SPIKES, Biomes.MODIFIED_JUNGLE, Biomes.MODIFIED_JUNGLE_EDGE, Biomes.TALL_BIRCH_FOREST, Biomes.TALL_BIRCH_HILLS, Biomes.DARK_FOREST_HILLS, Biomes.SNOWY_TAIGA_MOUNTAINS, Biomes.GIANT_SPRUCE_TAIGA, Biomes.GIANT_SPRUCE_TAIGA_HILLS, Biomes.MODIFIED_GRAVELLY_MOUNTAINS, Biomes.SHATTERED_SAVANNA, Biomes.SHATTERED_SAVANNA_PLATEAU, Biomes.ERODED_BADLANDS, Biomes.MODIFIED_WOODED_BADLANDS_PLATEAU, Biomes.MODIFIED_BADLANDS_PLATEAU});
}
}
@@ -1,55 +1,45 @@
package kaptainwutax.seedcracker.cracker;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.SeedData;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import kaptainwutax.seedcracker.util.Rand;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class PillarData extends SeedData {
public class PillarData {
private List<Integer> heights;
private List<Integer> heights;
public PillarData(List<Integer> heights) {
this.heights = heights;
}
public PillarData(List<Integer> heights) {
this.heights = heights;
}
@Override
public boolean test(long seed, Rand rand) {
List<Integer> h = this.getPillarHeights((int)seed);
return h.equals(this.heights);
}
public List<Integer> getPillarSeeds() {
List<Integer> result = new ArrayList<>();
public List<Integer> getPillarHeights(int pillarSeed) {
List<Integer> indices = new ArrayList<>();
for(int pillarSeed = 0; pillarSeed < (1 << 16); pillarSeed++) {
List<Integer> h = this.getPillarHeights(pillarSeed);
if(h.equals(heights))result.add(pillarSeed);
}
for(int i = 0; i < 10; i++) {
indices.add(i);
}
return result;
}
Collections.shuffle(indices, new Random(pillarSeed));
public List<Integer> getPillarHeights(int spikeSeed) {
List<Integer> indices = new ArrayList<>();
List<Integer> heights = new ArrayList<>();
for (int i = 0; i < 10; i++) {
indices.add(i);
}
for(Integer index : indices) {
heights.add(76 + index * 3);
}
Collections.shuffle(indices, new Random(spikeSeed));
return heights;
}
List<Integer> heights = new ArrayList<>();
@Override
public double getBits() {
return 16;
}
for (Integer index: indices) {
heights.add(76 + index * 3);
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.PILLARS);
}
return heights;
}
}
@@ -1,38 +0,0 @@
package kaptainwutax.seedcracker.cracker;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.SeedData;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.Seeds;
import net.minecraft.util.math.ChunkPos;
public class SlimeChunkData extends SeedData {
protected static final double BITS = Math.log(10) / Math.log(2);
protected final ChunkPos chunkPos;
protected final boolean isSlimeChunk;
public SlimeChunkData(ChunkPos chunkPos, boolean isSlimeChunk) {
this.chunkPos = chunkPos;
this.isSlimeChunk = isSlimeChunk;
}
@Override
public boolean test(long seed, Rand rand) {
Seeds.setSlimeChunkSeed(rand, seed, this.chunkPos.x, this.chunkPos.z, 987234911L);
return (rand.nextInt(10) == 0) == this.isSlimeChunk;
}
@Override
public double getBits() {
return BITS;
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.STRUCTURES);
}
}
@@ -1,38 +0,0 @@
package kaptainwutax.seedcracker.cracker;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
import java.util.List;
import java.util.Random;
public class SpawnPointData {
private BlockPos center;
private int distanceSquared;
public SpawnPointData(BlockPos center, int maxDistance) {
this.center = center;
this.distanceSquared = maxDistance * maxDistance;
}
public boolean test(FakeBiomeSource source) {
BlockPos spawnPos = getSpawnPoint(source);
int distanceX = spawnPos.getX() - this.center.getX();
distanceX *= distanceX;
int distanceZ = spawnPos.getZ() - this.center.getZ();
distanceZ *= distanceZ;
return distanceX + distanceZ <= this.distanceSquared;
}
public static BlockPos getSpawnPoint(FakeBiomeSource source) {
List<Biome> spawnBiomes = source.getSpawnBiomes();
Random random = new Random(source.getSeed());
BlockPos spawnPos = source.locateBiome(0, 63, 0, 256, spawnBiomes, random);
ChunkPos chunkPos = spawnPos == null ? new ChunkPos(0, 0) : new ChunkPos(spawnPos);
return chunkPos.getCenterBlockPos().add(0, 64, 0);
}
}
@@ -0,0 +1,172 @@
package kaptainwutax.seedcracker.cracker;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.gen.ChunkRandom;
public class StructureData {
private int regionX;
private int regionZ;
private int offsetX;
private int offsetZ;
private Feature feature;
public StructureData(ChunkPos chunkPos, Feature feature) {
this.feature = feature;
this.feature.build(this, chunkPos);
}
public int getRegionX() {
return this.regionX;
}
public int getRegionZ() {
return this.regionZ;
}
public int getOffsetX() {
return this.offsetX;
}
public int getOffsetZ() {
return this.offsetZ;
}
public int getSalt() {
return this.feature.salt;
}
public Feature getFeature() {
return this.feature;
}
public boolean test(ChunkRandom rand) {
return this.feature.test(rand, this.offsetX, this.offsetZ);
}
@Override
public boolean equals(Object obj) {
if(obj == this)return true;
if(obj instanceof StructureData) {
StructureData structureData = ((StructureData)obj);
return structureData.regionX == this.regionX && structureData.regionZ == this.regionZ && structureData.feature == this.feature;
}
return false;
}
public abstract static class Feature {
public final int salt;
public final int distance;
public Feature(int salt, int distance) {
this.salt = salt;
this.distance = distance;
}
public void build(StructureData data, ChunkPos chunkPos) {
int chunkX = chunkPos.x;
int chunkZ = chunkPos.z;
chunkX = chunkX < 0 ? chunkX - this.distance + 1 : chunkX;
chunkZ = chunkZ < 0 ? chunkZ - this.distance + 1 : chunkZ;
//Pick out in which region the chunk is.
int regionX = (chunkX / this.distance);
int regionZ = (chunkZ / this.distance);
data.regionX = regionX;
data.regionZ = regionZ;
regionX *= this.distance;
regionZ *= this.distance;
data.offsetX = chunkPos.x - regionX;
data.offsetZ = chunkPos.z - regionZ;
}
public abstract boolean test(ChunkRandom rand, int x, int z);
}
public static final Feature DESERT_PYRAMID = new Feature(14357617, 32) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextInt(24) == x && rand.nextInt(24) == z;
}
};
public static final Feature IGLOO = new Feature(14357618, 32) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextInt(24) == x && rand.nextInt(24) == z;
}
};
public static final Feature JUNGLE_TEMPLE = new Feature(14357619, 32) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextInt(24) == x && rand.nextInt(24) == z;
}
};
public static final Feature SWAMP_HUT = new Feature(14357620, 32) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextInt(24) == x && rand.nextInt(24) == z;
}
};
public static final Feature OCEAN_RUIN = new Feature(14357621, 16) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextInt(8) == x && rand.nextInt(8) == z;
}
};
public static final Feature SHIPWRECK = new Feature(165745295, 16) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextInt(8) == x && rand.nextInt(8) == z;
}
};
public static final Feature PILLAGER_OUTPOST = new Feature(165745296, 32) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextInt(24) == x && rand.nextInt(24) == z;
}
};
public static final Feature END_CITY = new Feature(10387313, 20) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return (rand.nextInt(9) + rand.nextInt(9)) / 2 == x
&& (rand.nextInt(9) + rand.nextInt(9)) / 2 == z;
}
};
public static final Feature OCEAN_MONUMENT = new Feature(10387313, 32) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return (rand.nextInt(27) + rand.nextInt(27)) / 2 == x
&& (rand.nextInt(27) + rand.nextInt(27)) / 2 == z;
}
};
public static final Feature BURIED_TREASURE = new Feature(10387320, 1) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextFloat() < 0.1f;
}
};
public static final Feature WOODLAND_MANSION = new Feature(10387319, 80) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return (rand.nextInt(60) + rand.nextInt(60)) / 2 == x
&& (rand.nextInt(60) + rand.nextInt(60)) / 2 == z;
}
};
}
@@ -0,0 +1,62 @@
package kaptainwutax.seedcracker.cracker;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.population.PopulationData;
import kaptainwutax.seedcracker.util.Log;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.math.LCG;
import net.minecraft.world.gen.ChunkRandom;
import java.util.List;
public class TimeMachine {
private LCG inverseLCG = Rand.JAVA_LCG.combine(-2);
public TimeMachine() {
}
public List<Long> buildStructureSeeds(int pillarSeed, List<StructureData> structureDataList, List<PopulationData> populationDataList, List<Long> structureSeeds) {
ChunkRandom chunkRandom = new ChunkRandom();
for(long i = 0; i < (1L << 32); i++) {
if((i & ((1L << 28) - 1)) == 0) {
Log.warn("Progress " + (i * 100.0f) / (1L << 32) + "%...");
}
long structureSeed = this.timeMachine(i, pillarSeed);
boolean goodSeed = true;
for(StructureData structureData: structureDataList) {
if(!goodSeed)break;
chunkRandom.setStructureSeed(structureSeed, structureData.getRegionX(),
structureData.getRegionZ(), structureData.getSalt());
if(!structureData.test(chunkRandom))goodSeed = false;
}
for(PopulationData populationData: populationDataList) {
if(!goodSeed)break;
if(!populationData.test(structureSeed))goodSeed = false;
}
if(goodSeed) {
structureSeeds.add(structureSeed);
}
}
return structureSeeds;
}
public long timeMachine(long partialWorldSeed, int pillarSeed) {
long currentSeed = 0L;
currentSeed |= (partialWorldSeed & 0xFFFF0000L) << 16;
currentSeed |= (long)pillarSeed << 16;
currentSeed |= partialWorldSeed & 0xFFFFL;
currentSeed = this.inverseLCG.nextSeed(currentSeed);
currentSeed ^= Rand.JAVA_LCG.multiplier;
return currentSeed;
}
}
@@ -1,55 +0,0 @@
package kaptainwutax.seedcracker.cracker.population;
import kaptainwutax.seedcracker.cracker.storage.SeedData;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.Seeds;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
public abstract class DecoratorData extends SeedData {
private final ChunkPos chunkPos;
private final int salt;
private final Biome biome;
public DecoratorData(ChunkPos chunkPos, int salt, Biome biome) {
this.chunkPos = chunkPos;
this.salt = salt;
this.biome = biome;
}
@Override
public final boolean test(long seed, Rand rand) {
long decoratorSeed = Seeds.setPopulationSeed(null, seed, this.chunkPos.x << 4, this.chunkPos.z << 4);
decoratorSeed += salt;
decoratorSeed ^= Rand.JAVA_LCG.multiplier;
decoratorSeed &= Rand.JAVA_LCG.modulo - 1;
rand.setSeed(decoratorSeed, false);
return this.testDecorator(rand);
}
public abstract boolean testDecorator(Rand rand);
public ChunkPos getChunkPos() {
return this.chunkPos;
}
@Override
public boolean equals(Object obj) {
if(obj == this)return true;
if(obj instanceof DecoratorData) {
DecoratorData decoratorData = ((DecoratorData)obj);
return decoratorData.chunkPos.equals(this.chunkPos) && decoratorData.salt == this.salt;
}
return false;
}
@Override
public int hashCode() {
return this.chunkPos.hashCode() * 31 + this.salt;
}
}
@@ -1,39 +0,0 @@
package kaptainwutax.seedcracker.cracker.population;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import kaptainwutax.seedcracker.util.Rand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
public class DesertWellData extends DecoratorData {
public static final int SALT = 30010;
private static final double BITS = Math.log(1000 * 16 * 16) / Math.log(2);
private BlockPos pos;
public DesertWellData(ChunkPos chunkPos, Biome biome, BlockPos pos) {
super(chunkPos, SALT, biome);
this.pos = new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15);
}
@Override
public boolean testDecorator(Rand rand) {
if(rand.nextFloat() >= 0.001F)return false;
if(rand.nextInt(16) != this.pos.getX())return false;
if(rand.nextInt(16) != this.pos.getZ())return false;
return true;
}
@Override
public double getBits() {
return BITS;
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.STRUCTURES);
}
}
@@ -1,66 +1,60 @@
package kaptainwutax.seedcracker.cracker.population;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.math.LCG;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.decorator.Decorator;
import java.util.List;
public class DungeonData extends DecoratorData {
public class DungeonData extends PopulationData {
private static final double BITS = Math.log(256 * 16 * 16 * 0.125D) / Math.log(2);
public static final int SALT = 20003;
private static LCG REVERSE_SKIP = Rand.JAVA_LCG.combine(-1);
private static LCG Y_START_SKIP = Rand.JAVA_LCG.combine(2);
public static LCG REVERSE_SKIP = Rand.JAVA_LCG.combine(-1);
public static LCG Y_START_SKIP = Rand.JAVA_LCG.combine(2);
public static LCG Y_SKIP = Rand.JAVA_LCG.combine(5);
public static final Integer COBBLESTONE_CALL = 0;
public static final Integer MOSSY_COBBLESTONE_CALL = 1;
private BlockPos start;
private List<BlockPos> starts;
private final List<List<Integer>> floorCallsList;
public DungeonData(ChunkPos chunkPos, Biome biome, BlockPos start, List<List<Integer>> floorCallsList) {
super(chunkPos, SALT, biome);
this.start = start;
public DungeonData(ChunkPos chunkPos, Biome biome, List<BlockPos> starts, List<List<Integer>> floorCallsList) {
super(chunkPos, Decorator.DUNGEONS, biome);
this.starts = starts;
this.floorCallsList = floorCallsList;
}
@Override
public boolean testDecorator(Rand rand) {
public boolean testDecorator(long decoratorSeed) {
if(this.starts.isEmpty())return true;
//TODO: This currently only supports 1 dungeon per chunk.
BlockPos start = this.starts.get(0);
long currentSeed = decoratorSeed;
boolean valid = false;
for(int i = 0; i < 8; i++) {
int x = rand.nextInt(16);
int z = rand.nextInt(16);
int y = rand.nextInt(256);
currentSeed = i == 0 ? Y_START_SKIP.nextSeed(currentSeed) : Y_SKIP.nextSeed(currentSeed);
if(y == this.start.getY() && x == this.start.getX() && z == this.start.getZ()) {
return true;
if(currentSeed >> 40 == start.getY()) {
valid = true;
break;
}
rand.nextInt(2);
rand.nextInt(2);
}
return false;
}
if(!valid)return false;
public BlockPos getStart() {
return this.start;
}
int x = (int)(REVERSE_SKIP.nextSeed(currentSeed) >> 44);
if(x != start.getX())return false;
@Override
public double getBits() {
return BITS;
}
int z = (int)(Rand.JAVA_LCG.nextSeed(currentSeed) >> 44);
if(z != start.getZ())return false;
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.STRUCTURES);
return true;
}
}
@@ -1,22 +1,18 @@
package kaptainwutax.seedcracker.cracker.population;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.math.LCG;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.decorator.Decorator;
import java.util.List;
import java.util.stream.Collectors;
public class EmeraldOreData extends DecoratorData {
public class EmeraldOreData extends PopulationData {
private static final double BITS = Math.log(28 * 16 * 16 * 0.5D) / Math.log(2);
public static final int SALT = 40014;
private static final LCG[] SKIP = {
public static final LCG[] SKIP = {
Rand.JAVA_LCG.combine(0),
Rand.JAVA_LCG.combine(1),
Rand.JAVA_LCG.combine(2),
@@ -26,7 +22,7 @@ public class EmeraldOreData extends DecoratorData {
private List<BlockPos> starts;
public EmeraldOreData(ChunkPos chunkPos, Biome biome, List<BlockPos> ores) {
super(chunkPos, SALT, biome);
super(chunkPos, Decorator.EMERALD_ORE, biome);
this.starts = ores.stream().map(pos ->
new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15)
@@ -34,18 +30,19 @@ public class EmeraldOreData extends DecoratorData {
}
@Override
public boolean testDecorator(Rand rand) {
public boolean testDecorator(long decoratorSeed) {
if(this.starts.isEmpty())return true;
//TODO: This currently only supports 1 emerald per chunk.
BlockPos start = this.starts.get(0);
Rand rand = new Rand(decoratorSeed, false);
int b = rand.nextInt(6);
for(int i = 0; i < b + 3; i++) {
int x = rand.nextInt(16);
int z = rand.nextInt(16);
int y = rand.nextInt(28) + 4;
int z = rand.nextInt(16);
if(y == start.getY() && x == start.getX() && z == start.getZ()) {
return true;
@@ -55,14 +52,4 @@ public class EmeraldOreData extends DecoratorData {
return false;
}
@Override
public double getBits() {
return BITS;
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.STRUCTURES);
}
}
@@ -1,30 +1,28 @@
package kaptainwutax.seedcracker.cracker.population;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import kaptainwutax.seedcracker.util.Rand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.decorator.Decorator;
public class EndGatewayData extends DecoratorData {
private static final double BITS = Math.log(700 * 16 * 16 * 7) / Math.log(2);
private static final int SALT = 30000;
public class EndGatewayData extends PopulationData {
private int xOffset;
private int zOffset;
private int height;
public EndGatewayData(ChunkPos chunkPos, Biome biome, BlockPos pos, int height) {
super(chunkPos, SALT, biome);
super(chunkPos, Decorator.END_GATEWAY, biome);
this.xOffset = pos.getX() & 15;
this.zOffset = pos.getZ() & 15;
this.height = height;
}
@Override
public boolean testDecorator(Rand rand) {
public boolean testDecorator(long decoratorSeed) {
Rand rand = new Rand(decoratorSeed, false);
if(rand.nextInt(700) != 0)return false;
if(rand.nextInt(16) != this.xOffset)return false;
if(rand.nextInt(16) != this.zOffset)return false;
@@ -33,14 +31,4 @@ public class EndGatewayData extends DecoratorData {
return true;
}
@Override
public double getBits() {
return BITS;
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.STRUCTURES);
}
}
@@ -0,0 +1,104 @@
package kaptainwutax.seedcracker.cracker.population;
import kaptainwutax.seedcracker.cracker.DecoratorCache;
import kaptainwutax.seedcracker.util.Rand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkRandom;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.decorator.ConfiguredDecorator;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.DecoratedFeatureConfig;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class PopulationData {
private final ChunkPos chunkPos;
private final Decorator<?> decorator;
private final Biome biome;
public PopulationData(ChunkPos chunkPos, Decorator<?> decorator, Biome biome) {
this.chunkPos = chunkPos;
this.decorator = decorator;
this.biome = biome;
}
public final boolean test(long structureSeed) {
long decoratorSeed = this.getPopulationSeed(structureSeed, this.chunkPos.x << 4, this.chunkPos.z << 4);
int salt = DecoratorCache.get().getSalt(this.biome, this.decorator, true);
if(salt == DecoratorCache.INVALID) {
return false;
}
decoratorSeed += salt;
decoratorSeed ^= Rand.JAVA_LCG.multiplier;
decoratorSeed &= Rand.JAVA_LCG.modulo - 1;
return this.testDecorator(decoratorSeed);
}
public long getPopulationSeed(long structureSeed, int x, int z) {
Rand rand = new Rand(structureSeed, true);
long a = rand.nextLong() | 1L;
long b = rand.nextLong() | 1L;
return (long)x * a + (long)z * b ^ structureSeed;
}
public abstract boolean testDecorator(long decoratorSeed);
@Override
public boolean equals(Object obj) {
if(obj == this)return true;
if(obj instanceof PopulationData) {
PopulationData populationData = ((PopulationData)obj);
return populationData.chunkPos.equals(this.chunkPos) && populationData.decorator == this.decorator;
}
return false;
}
public abstract static class Feature {
private Map<Biome, Long> CACHE = new HashMap<>();
private GenerationStep.Feature genStep;
private Decorator decorator;
public Feature(GenerationStep.Feature genStep, Decorator decorator) {
this.genStep = genStep;
this.decorator = decorator;
}
public ChunkRandom buildRand(long worldSeed, Biome biome, ChunkPos chunkPos) {
if(CACHE.containsKey(biome)) {
return new ChunkRandom(CACHE.get(biome));
}
List<ConfiguredFeature<?>> features = biome.getFeaturesForStep(this.genStep);
for(int i = 0; i < features.size(); i++) {
ConfiguredFeature<?> feature = features.get(i);
if(!(feature.config instanceof DecoratedFeatureConfig))continue;
ConfiguredDecorator<?> currentDecorator = ((DecoratedFeatureConfig)feature.config).decorator;
if(currentDecorator.decorator == this.decorator) {
BlockPos pos = new BlockPos(chunkPos.getStartX(), 0, chunkPos.getStartZ());
ChunkRandom chunkRandom = new ChunkRandom();
long populationSeed = chunkRandom.setSeed(worldSeed, pos.getX(), pos.getZ());
long seed = chunkRandom.setFeatureSeed(populationSeed, i, this.genStep.ordinal());
CACHE.put(biome, seed ^ Rand.JAVA_LCG.multiplier);
return chunkRandom;
}
}
return null;
}
}
}
@@ -1,122 +0,0 @@
package kaptainwutax.seedcracker.cracker.storage;
import io.netty.util.internal.ConcurrentSet;
import kaptainwutax.seedcracker.cracker.BiomeData;
import kaptainwutax.seedcracker.cracker.PillarData;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.util.Log;
import java.util.Comparator;
import java.util.Set;
import java.util.function.Consumer;
public class DataStorage {
public static Comparator<SeedData> SEED_DATA_COMPARATOR = (s1, s2) -> {
boolean isStructure1 = s1 instanceof StructureData;
boolean isStructure2 = s2 instanceof StructureData;
if(isStructure1 != isStructure2) {
return isStructure2 ? 1: -1;
}
if(s1.equals(s2)) {
return 0;
}
double diff = s2.getBits() - s1.getBits();
return diff == 0.0D ? 1 : (int)Math.signum(diff);
};
protected TimeMachine timeMachine = new TimeMachine(this);
protected Set<Consumer<DataStorage>> scheduledData = new ConcurrentSet<>();
protected PillarData pillarData = null;
protected ScheduledSet<SeedData> baseSeedData = new ScheduledSet<>(SEED_DATA_COMPARATOR);
protected ScheduledSet<BiomeData> biomeSeedData = new ScheduledSet<>(null);
protected HashedSeedData hashedSeedData = null;
public void tick() {
if(!this.timeMachine.isRunning) {
this.baseSeedData.dump();
this.biomeSeedData.dump();
this.scheduledData.removeIf(c -> {
c.accept(this);
return true;
});
}
}
public synchronized boolean addPillarData(PillarData pillarData) {
boolean isAdded = this.pillarData == null;
if(isAdded && pillarData != null) {
this.pillarData = pillarData;
this.schedule(pillarData::onDataAdded);
}
return isAdded;
}
public synchronized boolean addBaseData(SeedData seedData) {
if(this.baseSeedData.contains(seedData)) {
return false;
}
this.baseSeedData.scheduleAdd(seedData);
this.schedule(seedData::onDataAdded);
return true;
}
public synchronized boolean addBiomeData(BiomeData biomeData) {
if(this.biomeSeedData.contains(biomeData)) {
return false;
}
this.biomeSeedData.scheduleAdd(biomeData);
this.schedule(biomeData::onDataAdded);
return true;
}
public synchronized boolean addHashedSeedData(HashedSeedData hashedSeedData) {
if(this.hashedSeedData == null || this.hashedSeedData.getHashedSeed() != hashedSeedData.getHashedSeed()) {
Log.warn("Fetched hashed world seed [" + hashedSeedData.getHashedSeed() + "].");
this.hashedSeedData = hashedSeedData;
this.schedule(hashedSeedData::onDataAdded);
return true;
}
return false;
}
public void schedule(Consumer<DataStorage> consumer) {
this.scheduledData.add(consumer);
}
public TimeMachine getTimeMachine() {
return this.timeMachine;
}
public double getBaseBits() {
double bits = 0.0D;
for(SeedData baseSeedDatum: this.baseSeedData) {
bits += baseSeedDatum.getBits();
}
return bits;
}
public void clear() {
System.out.println("Clearing data storage.");
this.scheduledData = new ConcurrentSet<>();
this.pillarData = null;
this.baseSeedData = new ScheduledSet<>(SEED_DATA_COMPARATOR);
this.biomeSeedData = new ScheduledSet<>(null);
this.hashedSeedData = null;
this.timeMachine.shouldTerminate = true;
this.timeMachine = new TimeMachine(this);
}
}
@@ -1,33 +0,0 @@
package kaptainwutax.seedcracker.cracker.storage;
import kaptainwutax.seedcracker.util.Rand;
import net.minecraft.world.level.LevelProperties;
public class HashedSeedData extends SeedData {
private final long hashedSeed;
public HashedSeedData(long hashedSeed) {
this.hashedSeed = hashedSeed;
}
@Override
public boolean test(long seed, Rand rand) {
return LevelProperties.sha256Hash(seed) == this.hashedSeed;
}
public long getHashedSeed() {
return this.hashedSeed;
}
@Override
public double getBits() {
return 64;
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.BIOMES);
}
}
@@ -1,7 +0,0 @@
package kaptainwutax.seedcracker.cracker.storage;
public interface ISeedStorage {
void onDataAdded(DataStorage dataStorage);
}
@@ -1,27 +0,0 @@
package kaptainwutax.seedcracker.cracker.storage;
import kaptainwutax.seedcracker.util.Log;
public class ProgressListener {
protected float progress;
protected int count = 0;
public ProgressListener() {
this(0.0F);
}
public ProgressListener(float progress) {
this.progress = progress;
}
public synchronized void addPercent(float percent, boolean debug) {
if((this.count & 3) == 0 && debug) {
Log.debug("Progress: " + this.progress + "%");
}
this.count++;
this.progress += percent;
}
}
@@ -1,48 +0,0 @@
package kaptainwutax.seedcracker.cracker.storage;
import java.util.*;
public class ScheduledSet<T> implements Iterable<T> {
protected final Set<T> baseSet;
protected final Set<T> scheduledSet;
public ScheduledSet(Comparator<T> comparator) {
if(comparator != null) {
this.baseSet = new TreeSet<>(comparator);
} else {
this.baseSet = new HashSet<>();
}
this.scheduledSet = new HashSet<>();
}
public synchronized void scheduleAdd(T e) {
this.scheduledSet.add(e);
}
public synchronized void dump() {
synchronized(this.baseSet) {
this.baseSet.addAll(this.scheduledSet);
this.scheduledSet.clear();
}
}
public synchronized boolean contains(T e) {
return this.baseSet.contains(e) || this.scheduledSet.contains(e);
}
public Set<T> getBaseSet() {
return this.baseSet;
}
@Override
public synchronized Iterator<T> iterator() {
return this.baseSet.iterator();
}
public synchronized int size() {
return this.baseSet.size();
}
}
@@ -1,11 +0,0 @@
package kaptainwutax.seedcracker.cracker.storage;
import kaptainwutax.seedcracker.util.Rand;
public abstract class SeedData implements ISeedStorage {
public abstract boolean test(long seed, Rand rand);
public abstract double getBits();
}
@@ -1,251 +0,0 @@
package kaptainwutax.seedcracker.cracker.storage;
import kaptainwutax.seedcracker.cracker.BiomeData;
import kaptainwutax.seedcracker.cracker.FakeBiomeSource;
import kaptainwutax.seedcracker.util.Log;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.math.LCG;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class TimeMachine {
public static ExecutorService SERVICE = Executors.newFixedThreadPool(5);
private LCG inverseLCG = Rand.JAVA_LCG.combine(-2);
protected DataStorage dataStorage;
public boolean isRunning = false;
public boolean shouldTerminate = false;
protected List<Integer> pillarSeeds = null;
protected List<Long> structureSeeds = null;
protected List<Long> worldSeeds = null;
public TimeMachine(DataStorage dataStorage) {
this.dataStorage = dataStorage;
}
public void poke(Phase phase) {
if(this.isRunning) {
return;
}
this.isRunning = true;
final Phase[] finalPhase = {phase};
SERVICE.submit(() -> {
while(finalPhase[0] != null && !this.shouldTerminate) {
if(finalPhase[0] == Phase.PILLARS) {
if(!this.pokePillars())break;
} else if(finalPhase[0] == Phase.STRUCTURES) {
if(!this.pokeStructures())break;
} else if(finalPhase[0] == Phase.BIOMES) {
if(!this.pokeBiomes())break;
}
finalPhase[0] = finalPhase[0].nextPhase();
}
this.isRunning = false;
});
}
protected boolean pokePillars() {
if(this.pillarSeeds != null || this.dataStorage.pillarData == null)return false;
this.pillarSeeds = new ArrayList<>();
Log.debug("====================================");
Log.warn("Looking for pillar seeds...");
for(int pillarSeed = 0; pillarSeed < 1 << 16 && !this.shouldTerminate; pillarSeed++) {
if(this.dataStorage.pillarData.test(pillarSeed, null)) {
Log.warn("Found pillar seed [" + pillarSeed + "].");
this.pillarSeeds.add(pillarSeed);
}
}
if(!this.pillarSeeds.isEmpty()) {
Log.warn("Finished searching for pillar seeds.");
} else {
Log.error("Finished search with no results.");
}
return true;
}
protected boolean pokeStructures() {
if(this.pillarSeeds == null || this.dataStorage.getBaseBits() < 54.0D)return false;
this.structureSeeds = new ArrayList<>();
SeedData[] cache = new SeedData[this.dataStorage.baseSeedData.size()];
int id = 0;
for(SeedData baseSeedDatum: this.dataStorage.baseSeedData) {
cache[id++] = baseSeedDatum;
}
for(int pillarSeed: this.pillarSeeds) {
Log.debug("====================================");
Log.warn("Looking for structure seeds with pillar seed [" + pillarSeed + "]...");
AtomicInteger completion = new AtomicInteger();
ProgressListener progressListener = new ProgressListener();
for(int threadId = 0; threadId < 4; threadId++) {
int fThreadId = threadId;
SERVICE.submit(() -> {
Rand rand = new Rand(0L, false);
long lower = (long)fThreadId * (1L << 30);
long upper = (long)(fThreadId + 1) * (1L << 30);
for(long partialWorldSeed = lower; partialWorldSeed < upper && !this.shouldTerminate; partialWorldSeed++) {
if((partialWorldSeed & ((1 << 27) - 1)) == 0) {
progressListener.addPercent(3.125F, true);
}
long seed = this.timeMachine(partialWorldSeed, pillarSeed);
boolean matches = true;
for(SeedData baseSeedDatum: cache) {
boolean test = baseSeedDatum.test(seed, rand);
if(!test) {
matches = false;
break;
}
}
if(matches) {
this.structureSeeds.add(seed);
Log.warn("Found structure seed [" + seed + "].");
}
}
completion.getAndIncrement();
});
}
while(completion.get() != 4) {
try {Thread.sleep(50);}
catch(InterruptedException e) {e.printStackTrace();}
if(this.shouldTerminate) {
return false;
}
}
progressListener.addPercent(0.0F, true);
}
if(!this.structureSeeds.isEmpty()) {
Log.warn("Finished searching for structure seeds.");
} else {
Log.error("Finished search with no results.");
}
return true;
}
protected boolean pokeBiomes() {
if(this.structureSeeds == null || this.worldSeeds != null)return false;
if(this.dataStorage.hashedSeedData == null && this.dataStorage.biomeSeedData.size() < 5)return false;
this.worldSeeds = new ArrayList<>();
Log.debug("====================================");
Log.warn("Looking for world seeds...");
if(this.dataStorage.hashedSeedData != null) {
for(long structureSeed: this.structureSeeds) {
for(long upperBits = 0; upperBits < 1 << 16; upperBits++) {
long worldSeed = (upperBits << 48) | structureSeed;
if(!this.dataStorage.hashedSeedData.test(worldSeed, null)) {
continue;
} else {
this.worldSeeds.add(worldSeed);
Log.warn("Found world seed [" + worldSeed + "].");
}
if(this.shouldTerminate) {
return false;
}
}
}
if(!this.worldSeeds.isEmpty()) {
Log.warn("Finished searching for world seeds.");
return true;
} else {
Log.error("Finished search with no results, reverting back to biomes.");
}
}
Log.warn("Looking for world seeds...");
for(long structureSeed: this.structureSeeds) {
for(long upperBits = 0; upperBits < 1 << 16; upperBits++) {
long worldSeed = (upperBits << 48) | structureSeed;
FakeBiomeSource source = new FakeBiomeSource(worldSeed);
boolean matches = true;
for(BiomeData biomeSeedDatum: this.dataStorage.biomeSeedData) {
if(!biomeSeedDatum.test(source)) {
matches = false;
break;
}
}
if(matches) {
this.worldSeeds.add(worldSeed);
Log.warn("Found world seed [" + worldSeed + "].");
}
if(this.shouldTerminate) {
return false;
}
}
}
if(!this.worldSeeds.isEmpty()) {
Log.warn("Finished searching for world seeds.");
} else {
Log.error("Finished search with no results.");
}
return true;
}
public long timeMachine(long partialWorldSeed, int pillarSeed) {
long currentSeed = 0L;
currentSeed |= (partialWorldSeed & 0xFFFF0000L) << 16;
currentSeed |= (long)pillarSeed << 16;
currentSeed |= partialWorldSeed & 0xFFFFL;
currentSeed = this.inverseLCG.nextSeed(currentSeed);
currentSeed ^= Rand.JAVA_LCG.multiplier;
return currentSeed;
}
public enum Phase {
BIOMES(null), STRUCTURES(BIOMES), PILLARS(STRUCTURES);
private final Phase nextPhase;
Phase(Phase nextPhase) {
this.nextPhase = nextPhase;
}
public Phase nextPhase() {
return this.nextPhase;
}
}
}
@@ -1,61 +0,0 @@
package kaptainwutax.seedcracker.cracker.structure;
import kaptainwutax.seedcracker.cracker.storage.DataStorage;
import kaptainwutax.seedcracker.cracker.storage.SeedData;
import kaptainwutax.seedcracker.cracker.storage.TimeMachine;
import kaptainwutax.seedcracker.cracker.structure.type.FeatureType;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.Seeds;
import net.minecraft.util.math.ChunkPos;
public class StructureData extends SeedData {
public int chunkX;
public int chunkZ;
public int regionX;
public int regionZ;
public int offsetX;
public int offsetZ;
private final int salt;
private FeatureType<StructureData> featureType;
public StructureData(ChunkPos chunkPos, FeatureType<StructureData> featureType) {
this.featureType = featureType;
this.salt = this.featureType.salt;
this.featureType.build(this, chunkPos);
}
@Override
public boolean test(long structureSeed, Rand rand) {
Seeds.setRegionSeed(rand, structureSeed, this.regionX, this.regionZ, this.salt);
return this.featureType.test(rand, this, structureSeed);
}
@Override
public double getBits() {
return this.featureType.getBits();
}
@Override
public void onDataAdded(DataStorage dataStorage) {
dataStorage.getTimeMachine().poke(TimeMachine.Phase.STRUCTURES);
}
@Override
public boolean equals(Object obj) {
if(obj == this)return true;
if(obj instanceof StructureData) {
StructureData structureData = ((StructureData)obj);
return structureData.featureType == this.featureType && structureData.regionX == this.regionX && structureData.regionZ == this.regionZ;
}
return false;
}
@Override
public int hashCode() {
return this.regionX * 961 + this.regionZ * 31 + this.featureType.salt;
}
}
@@ -1,76 +0,0 @@
package kaptainwutax.seedcracker.cracker.structure;
import kaptainwutax.seedcracker.cracker.structure.type.AbstractTempleType;
import kaptainwutax.seedcracker.cracker.structure.type.FeatureType;
import kaptainwutax.seedcracker.cracker.structure.type.RarityType;
import kaptainwutax.seedcracker.cracker.structure.type.TriangularType;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.Seeds;
public class StructureFeatures {
public static final FeatureType<StructureData> DESERT_PYRAMID = new AbstractTempleType(14357617, 32, 24);
public static final FeatureType<StructureData> IGLOO = new AbstractTempleType(14357618, 32, 24);
public static final FeatureType<StructureData> JUNGLE_TEMPLE = new AbstractTempleType(14357619, 32, 24);
public static final FeatureType<StructureData> SWAMP_HUT = new AbstractTempleType(14357620, 32, 24);
public static final FeatureType<StructureData> OCEAN_RUIN = new AbstractTempleType(14357621, 16, 8);
public static final FeatureType<StructureData> SHIPWRECK = new AbstractTempleType(165745295, 16, 8);
public static final FeatureType<StructureData> PILLAGER_OUTPOST = new AbstractTempleType(165745296, 32, 24) {
@Override
public boolean test(Rand rand, StructureData data, long structureSeed) {
if(!super.test(rand, data, structureSeed))return false;
Seeds.setWeakSeed(rand, structureSeed, data.chunkX, data.chunkZ);
return rand.nextInt(5) == 0;
}
};
public static final FeatureType<StructureData> VILLAGE = new AbstractTempleType(10387312, 32, 24);
public static final FeatureType<StructureData> END_CITY = new TriangularType(10387313, 20, 9);
public static final FeatureType<StructureData> OCEAN_MONUMENT = new TriangularType(10387313, 32, 27);
public static final FeatureType<StructureData> WOODLAND_MANSION = new TriangularType(10387319, 80, 60);
public static final FeatureType<StructureData> BURIED_TREASURE = new RarityType(10387320, 1, 0.01F);
public static final FeatureType<StructureData> NETHER_FORTRESS = new FeatureType<StructureData>(-1, 1) {
protected final double bits = Math.log(3 * 8 * 8) / Math.log(2);
@Override
public boolean test(Rand rand, StructureData data, long structureSeed) {
Seeds.setWeakSeed(rand, structureSeed, data.chunkX, data.chunkZ);
return rand.nextInt(3) == 0
&& data.chunkX == ((data.chunkX >> 4) << 4) + 4 + rand.nextInt(8)
&& data.chunkZ == ((data.chunkZ >> 4) << 4) + 4 + rand.nextInt(8);
}
@Override
public double getBits() {
return this.bits;
}
};
public static final FeatureType<StructureData> MINESHAFT = new FeatureType<StructureData>(-1, 1) {
protected final double bits = Math.log(1.0D / 0.004D) / Math.log(2);
@Override
public boolean test(Rand rand, StructureData data, long structureSeed) {
Seeds.setStructureStartSeed(rand, structureSeed, data.chunkX, data.chunkZ);
return rand.nextDouble() < 0.004D;
}
@Override
public double getBits() {
return this.bits;
}
};
}
@@ -1,27 +0,0 @@
package kaptainwutax.seedcracker.cracker.structure.type;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.util.Rand;
public class AbstractTempleType extends FeatureType<StructureData> {
protected final int offset;
protected final double bits;
public AbstractTempleType(int salt, int distance, int offset) {
super(salt, distance);
this.offset = offset;
this.bits = Math.log(this.offset * this.offset) / Math.log(2);
}
@Override
public boolean test(Rand rand, StructureData data, long structureSeed) {
return rand.nextInt(this.offset) == data.offsetX && rand.nextInt(this.offset) == data.offsetZ;
}
@Override
public double getBits() {
return this.bits;
}
}
@@ -1,45 +0,0 @@
package kaptainwutax.seedcracker.cracker.structure.type;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.util.Rand;
import net.minecraft.util.math.ChunkPos;
public abstract class FeatureType<T extends StructureData> {
public final int salt;
public final int distance;
public FeatureType(int salt, int distance) {
this.salt = salt;
this.distance = distance;
}
public void build(T data, ChunkPos chunkPos) {
int chunkX = chunkPos.x;
int chunkZ = chunkPos.z;
data.chunkX = chunkX;
data.chunkZ = chunkZ;
chunkX = chunkX < 0 ? chunkX - this.distance + 1 : chunkX;
chunkZ = chunkZ < 0 ? chunkZ - this.distance + 1 : chunkZ;
//Pick out in which region the chunk is.
int regionX = (chunkX / this.distance);
int regionZ = (chunkZ / this.distance);
data.regionX = regionX;
data.regionZ = regionZ;
regionX *= this.distance;
regionZ *= this.distance;
data.offsetX = chunkPos.x - regionX;
data.offsetZ = chunkPos.z - regionZ;
}
public abstract boolean test(Rand rand, T data, long structureSeed);
public abstract double getBits();
}
@@ -1,27 +0,0 @@
package kaptainwutax.seedcracker.cracker.structure.type;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.util.Rand;
public class RarityType extends FeatureType<StructureData> {
private final float rarity;
private final double bits;
public RarityType(int salt, int distance, float rarity) {
super(salt, distance);
this.rarity = rarity;
this.bits = Math.log(1.0D / this.rarity) / Math.log(2);
}
@Override
public boolean test(Rand rand, StructureData data, long structureSeed) {
return rand.nextFloat() < this.rarity;
}
@Override
public double getBits() {
return this.bits;
}
}
@@ -1,32 +0,0 @@
package kaptainwutax.seedcracker.cracker.structure.type;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.util.Rand;
public class TriangularType extends FeatureType<StructureData> {
protected final int peak;
protected final double bits;
public TriangularType(int salt, int distance, int peak) {
super(salt, distance);
this.peak = peak;
this.bits = Math.log(this.peak * this.peak) / Math.log(2);
}
@Override
public boolean test(Rand rand, StructureData data, long structureSeed) {
return (rand.nextInt(this.peak) + rand.nextInt(this.peak)) / 2 == data.offsetX
&& (rand.nextInt(this.peak) + rand.nextInt(this.peak)) / 2 == data.offsetZ;
}
/*
* For this type specifically, the bits approximation is bad since the distribution is special.
*/
@Override
public double getBits() {
return this.bits;
}
}
@@ -0,0 +1,23 @@
package kaptainwutax.seedcracker.feature.decoration;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public abstract class DecorationFeature {
protected World world;
protected BlockPos pos;
public DecorationFeature(World world, BlockPos pos) {
this.world = world;
this.pos = pos;
}
public abstract void reverseSeed();
public Block getBlockAt(BlockPos pos) {
return this.world.getBlockState(pos).getBlock();
}
}
@@ -0,0 +1,91 @@
package kaptainwutax.seedcracker.feature.decoration;
import kaptainwutax.seedcracker.util.Rand;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
public class DungeonFeature extends DecorationFeature {
private static int MOSSY_COBBLESTONE_CALL = 0;
private static int COBBLESTONE_CALL = 1;
public DungeonFeature(World world, BlockPos pos) {
super(world, pos);
}
@Override
public void reverseSeed() {
BlockPos decoratorPos = this.getLocalPos(this.pos);
Vec3i dungeonSize = this.getDungeonSize(this.pos);
List<Integer> floorCalls = new ArrayList<>();
for(int xo = -dungeonSize.getX(); xo <= dungeonSize.getX(); xo++) {
for(int zo = -dungeonSize.getZ(); zo <= dungeonSize.getZ(); zo++) {
Block block = this.world.getBlockState(this.pos.add(xo, -1, zo)).getBlock();
if(block == Blocks.MOSSY_COBBLESTONE) {
floorCalls.add(MOSSY_COBBLESTONE_CALL);
} else if(block == Blocks.COBBLESTONE) {
floorCalls.add(COBBLESTONE_CALL);
}
}
}
List<Long> dungeonSeeds = this.getDungeonSeeds(dungeonSize, floorCalls);
List<Long> decoratorSeeds = new ArrayList<>();
for(long dungeonSeed: dungeonSeeds) {
long decoratorSeed = Rand.JAVA_LCG.combine(-3).nextSeed(dungeonSeed);
Rand rand = new Rand(decoratorSeed, false);
if(rand.nextInt(16) != decoratorPos.getX())continue;
if(rand.nextInt(256) != decoratorPos.getY())continue;
if(rand.nextInt(16) != decoratorPos.getZ())continue;
decoratorSeeds.add(decoratorSeed);
}
decoratorSeeds.forEach(System.out::println);
}
public BlockPos getLocalPos(BlockPos pos) {
return new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15);
}
public Vec3i getDungeonSize(BlockPos spawnerPos) {
for(int xo = 4; xo >= 3; xo--) {
for(int zo = 4; zo >= 3; zo--) {
Block block = this.getBlockAt(spawnerPos.add(xo, -1, zo));
if(block != Blocks.MOSSY_COBBLESTONE)continue;
if(block != Blocks.COBBLESTONE)continue;
return new Vec3i(xo, 0, zo);
}
}
return Vec3i.ZERO;
}
public List<Long> getDungeonSeeds(Vec3i dungeonSize, List<Integer> floorCalls) {
List<Long> floorSeeds = new ArrayList<>();
//TODO: Lattice magic to find floorSeeds from floorCalls.
List<Long> dungeonSeeds = new ArrayList<>();
for(long floorSeed: floorSeeds) {
long dungeonSeed = Rand.JAVA_LCG.combine(-2).nextSeed(floorSeed);
Rand rand = new Rand(dungeonSeed, false);
if(rand.nextInt(2) + 3 != dungeonSize.getX())continue;
if(rand.nextInt(2) + 3 != dungeonSize.getZ())continue;
dungeonSeeds.add(dungeonSeed);
}
return dungeonSeeds;
}
}
@@ -9,7 +9,6 @@ import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.Heightmap;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.dimension.DimensionType;
import java.util.ArrayList;
@@ -30,12 +29,7 @@ public class BiomeFinder extends Finder {
BlockPos blockPos = this.chunkPos.getCenterBlockPos().add(x, 0, z);
Biome biome = this.world.getBiome(blockPos);
//TODO: Fix this multi-threading issue.
if(biome == Biomes.THE_VOID) {
continue;
}
if(SeedCracker.get().getDataStorage().addBiomeData(new BiomeData(blockPos, biome))) {
if(SeedCracker.get().onBiomeData(new BiomeData(blockPos.getX(), blockPos.getZ(), biome))) {
blockPos = this.world.getTopPosition(Heightmap.Type.WORLD_SURFACE, blockPos).down();
result.add(blockPos);
}
@@ -17,7 +17,7 @@ public abstract class BlockFinder extends Finder {
public BlockFinder(World world, ChunkPos chunkPos, Block block) {
super(world, chunkPos);
this.targetBlockStates.addAll(block.getStateManager().getStates());
this.targetBlockStates.addAll(block.getStateFactory().getStates());
}
public BlockFinder(World world, ChunkPos chunkPos, BlockState... blockStates) {
@@ -0,0 +1,13 @@
package kaptainwutax.seedcracker.finder;
public class DefaultFinderConfig extends FinderConfig {
public DefaultFinderConfig() {
super();
this.typeStates.put(Type.DIAMOND_ORE, false);
this.typeStates.put(Type.INFESTED_STONE_ORE, false);
this.typeStates.put(Type.IGLOO, false);
this.typeStates.put(Type.MANSION, false);
}
}
@@ -1,13 +1,6 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.finder.population.DesertWellFinder;
import kaptainwutax.seedcracker.finder.population.DungeonFinder;
import kaptainwutax.seedcracker.finder.population.EndGatewayFinder;
import kaptainwutax.seedcracker.finder.population.EndPillarsFinder;
import kaptainwutax.seedcracker.finder.population.ore.EmeraldOreFinder;
import kaptainwutax.seedcracker.finder.structure.*;
import kaptainwutax.seedcracker.render.Renderer;
import kaptainwutax.seedcracker.util.FinderBuilder;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
@@ -16,10 +9,8 @@ import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public abstract class Finder {
@@ -33,8 +24,9 @@ public abstract class Finder {
static {
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
for(int y = 0; y < 256; y++) {
for(int y = 0; y < 256; y++) {
for(int z = 0; z < 16; z++) {
BlockPos pos = new BlockPos(x, y, z);
if(y < 16)SUB_CHUNK_POSITIONS.add(pos);
CHUNK_POSITIONS.add(pos);
@@ -63,17 +55,16 @@ public abstract class Finder {
DimensionType playerDim = mc.player.world.dimension.getType();
if(finderDim != playerDim)return false;
int renderDistance = mc.options.viewDistance * 16 + 16;
Vec3d playerPos = mc.player.getPos();
for(Renderer renderer: this.renderers) {
BlockPos pos = renderer.getPos();
double distance = playerPos.squaredDistanceTo(pos.getX(), playerPos.y, pos.getZ());
if(distance <= renderDistance * renderDistance + 32)return true;
}
double distance = playerPos.squaredDistanceTo(
this.chunkPos.x * 16,
playerPos.y,
this.chunkPos.z * 16
);
return false;
int renderDistance = mc.options.viewDistance * 16 + 16;
return distance <= renderDistance * renderDistance + 32;
}
public void render() {
@@ -98,42 +89,4 @@ public abstract class Finder {
return newList;
}
public enum Category {
STRUCTURES,
BIOMES,
ORES,
OTHERS
}
public enum Type {
BURIED_TREASURE(BuriedTreasureFinder::create, Category.STRUCTURES),
DESERT_TEMPLE(DesertTempleFinder::create, Category.STRUCTURES),
END_CITY(EndCityFinder::create, Category.STRUCTURES),
//IGLOO(IglooFinder::create, Category.STRUCTURES),
JUNGLE_TEMPLE(JungleTempleFinder::create, Category.STRUCTURES),
MONUMENT(OceanMonumentFinder::create, Category.STRUCTURES),
SWAMP_HUT(SwampHutFinder::create, Category.STRUCTURES),
//MANSION(MansionFinder::create, Category.STRUCTURES),
SHIPWRECK(ShipwreckFinder::create, Category.STRUCTURES),
END_PILLARS(EndPillarsFinder::create, Category.OTHERS),
END_GATEWAY(EndGatewayFinder::create, Category.OTHERS),
DUNGEON(DungeonFinder::create, Category.OTHERS),
EMERALD_ORE(EmeraldOreFinder::create, Category.ORES),
DESERT_WELL(DesertWellFinder::create, Category.OTHERS),
BIOME(BiomeFinder::create, Category.BIOMES);
public final FinderBuilder finderBuilder;
private final Category category;
Type(FinderBuilder finderBuilder, Category category) {
this.finderBuilder = finderBuilder;
this.category = category;
}
public static List<Type> getForCategory(Category category) {
return Arrays.stream(values()).filter(type -> type.category == category).collect(Collectors.toList());
}
}
}
@@ -1,26 +1,32 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.finder.profile.FinderProfile;
import kaptainwutax.seedcracker.finder.profile.NopeProfile;
import kaptainwutax.seedcracker.finder.population.DungeonFinder;
import kaptainwutax.seedcracker.finder.population.EndGatewayFinder;
import kaptainwutax.seedcracker.finder.population.EndPillarsFinder;
import kaptainwutax.seedcracker.finder.population.ore.DiamondOreFinder;
import kaptainwutax.seedcracker.finder.population.ore.EmeraldOreFinder;
import kaptainwutax.seedcracker.finder.population.ore.InfestedStoneOreFinder;
import kaptainwutax.seedcracker.finder.structure.*;
import kaptainwutax.seedcracker.util.FinderBuilder;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;
public class FinderConfig {
protected FinderProfile finderProfile = new NopeProfile();
protected Map<Finder.Type, ConcurrentLinkedQueue<Finder>> activeFinders = new ConcurrentHashMap<>();
protected Map<Type, Boolean> typeStates = new HashMap<>();
protected Map<Type, ConcurrentLinkedQueue<Finder>> activeFinders = new ConcurrentHashMap<>();
public FinderConfig() {
for(Type type: Type.values()) {
this.typeStates.put(type, true);
}
}
public List<Finder.Type> getActiveFinderTypes() {
return this.finderProfile.typeStates.entrySet().stream()
public List<Type> getActiveFinderTypes() {
return this.typeStates.entrySet().stream()
.filter(Map.Entry::getValue)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
@@ -35,7 +41,7 @@ public class FinderConfig {
.flatMap(Queue::stream).collect(Collectors.toList());
}
public void addFinder(Finder.Type type, Finder finder) {
public void addFinder(Type type, Finder finder) {
if(finder.isUseless())return;
if(!this.activeFinders.containsKey(type)) {
@@ -45,12 +51,51 @@ public class FinderConfig {
this.activeFinders.get(type).add(finder);
}
public boolean getTypeState(Finder.Type type) {
return this.finderProfile.typeStates.get(type);
public boolean getTypeState(Type type) {
return this.typeStates.get(type);
}
public boolean setTypeState(Finder.Type type, boolean flag) {
return this.finderProfile.setTypeState(type, flag);
public void setTypeState(Type type, boolean flag) {
this.typeStates.put(type, flag);
}
public enum Category {
STRUCTURES,
BIOMES,
ORES,
OTHERS
}
public enum Type {
BURIED_TREASURE(BuriedTreasureFinder::create, Category.STRUCTURES),
DESERT_TEMPLE(DesertTempleFinder::create, Category.STRUCTURES),
END_CITY(EndCityFinder::create, Category.STRUCTURES),
IGLOO(IglooFinder::create, Category.STRUCTURES),
JUNGLE_TEMPLE(JungleTempleFinder::create, Category.STRUCTURES),
MONUMENT(OceanMonumentFinder::create, Category.STRUCTURES),
SWAMP_HUT(SwampHutFinder::create, Category.STRUCTURES),
MANSION(MansionFinder::create, Category.STRUCTURES),
END_PILLARS(EndPillarsFinder::create, Category.OTHERS),
END_GATEWAY(EndGatewayFinder::create, Category.OTHERS),
DUNGEON(DungeonFinder::create, Category.OTHERS),
DIAMOND_ORE(DiamondOreFinder::create, Category.ORES),
INFESTED_STONE_ORE(InfestedStoneOreFinder::create, Category.ORES),
EMERALD_ORE(EmeraldOreFinder::create, Category.ORES),
BIOME(BiomeFinder::create, Category.BIOMES);
public final FinderBuilder finderBuilder;
private final Category category;
Type(FinderBuilder finderBuilder, Category category) {
this.finderBuilder = finderBuilder;
this.category = category;
}
public static List<Type> getForCategory(Category category) {
return Arrays.stream(values()).filter(type -> type.category == category).collect(Collectors.toList());
}
}
}
@@ -1,9 +1,6 @@
package kaptainwutax.seedcracker.finder;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import kaptainwutax.seedcracker.finder.profile.VanillaProfile;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
@@ -17,7 +14,7 @@ public class FinderQueue {
public static ExecutorService SERVICE = Executors.newFixedThreadPool(5);
public RenderType renderType = RenderType.XRAY;
public FinderConfig finderProfile = new FinderConfig();
public FinderConfig finderConfig = new DefaultFinderConfig();
private FinderQueue() {
this.clear();
@@ -28,30 +25,24 @@ public class FinderQueue {
}
public void onChunkData(World world, ChunkPos chunkPos) {
this.finderProfile.getActiveFinderTypes().forEach(type -> {
SERVICE.submit(() -> {
try {
List<Finder> finders = type.finderBuilder.build(world, chunkPos);
this.finderConfig.getActiveFinderTypes().forEach(type -> {
SERVICE.submit(() -> {
List<Finder> finders = type.finderBuilder.build(world, chunkPos);
finders.forEach(finder -> {
if(finder.isValidDimension(world.dimension.getType())) {
finder.findInChunk();
this.finderProfile.addFinder(type, finder);
}
});
} catch(Exception e) {
e.printStackTrace();
}
finders.forEach(finder -> {
if(finder.isValidDimension(world.dimension.getType())) {
this.finderConfig.addFinder(type, finder);
finder.findInChunk();
this.finderConfig.addFinder(type, finder);
}
});
});
});
}
public void renderFinders(MatrixStack matrixStack) {
public void renderFinders() {
if(this.renderType == RenderType.OFF)return;
RenderSystem.pushMatrix();
RenderSystem.multMatrix(matrixStack.peek().getModel());
GlStateManager.disableTexture();
//Makes it render through blocks.
@@ -59,18 +50,22 @@ public class FinderQueue {
GlStateManager.disableDepthTest();
}
this.finderProfile.getActiveFinders().forEach(finder -> {
this.finderConfig.getActiveFinders().forEach(finder -> {
if(finder.shouldRender()) {
finder.render();
}
});
RenderSystem.popMatrix();
GlStateManager.enableTexture();
if(this.renderType == RenderType.XRAY) {
GlStateManager.enableDepthTest();
}
}
public void clear() {
this.renderType = RenderType.XRAY;
this.finderProfile = new FinderConfig();
this.finderConfig = new DefaultFinderConfig();
}
public enum RenderType {
@@ -1,101 +0,0 @@
package kaptainwutax.seedcracker.finder.population;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.population.DesertWellData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.finder.structure.PieceFinder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.DesertBiome;
import net.minecraft.world.biome.DesertHillsBiome;
import net.minecraft.world.biome.DesertLakesBiome;
import net.minecraft.world.dimension.DimensionType;
import java.util.ArrayList;
import java.util.List;
public class DesertWellFinder extends PieceFinder {
protected static List<BlockPos> SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> {
return false;
});
protected static Vec3i SIZE = new Vec3i(5, 6, 5);
public DesertWellFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos, Direction.NORTH, SIZE);
this.searchPositions = SEARCH_POSITIONS;
this.buildStructure();
}
@Override
public List<BlockPos> findInChunk() {
Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(8, 0, 8));
if(!(biome instanceof DesertBiome) && !(biome instanceof DesertHillsBiome) && !(biome instanceof DesertLakesBiome)) {
return new ArrayList<>();
}
List<BlockPos> result = super.findInChunk();
result.forEach(pos -> {
pos = pos.add(2, 1, 2);
if(SeedCracker.get().getDataStorage().addBaseData(new DesertWellData(new ChunkPos(pos), biome, pos))) {
this.renderers.add(new Cuboid(pos.add(-2, -1, -2), SIZE, new Vector4f(0.5f, 0.5f, 1.0f, 1.0f)));
this.renderers.add(new Cube(pos, new Vector4f(0.5f, 0.5f, 1.0f, 1.0f)));
}
});
return result;
}
@Override
public boolean isValidDimension(DimensionType dimension) {
return dimension == DimensionType.OVERWORLD;
}
protected void buildStructure() {
BlockState sandstone = Blocks.SANDSTONE.getDefaultState();
BlockState sandstoneSlab = Blocks.SANDSTONE_SLAB.getDefaultState();
BlockState water = Blocks.WATER.getDefaultState();
this.fillWithOutline(0, 0, 0, 4, 1, 4, sandstone, sandstone, false);
this.fillWithOutline(1, 5, 1, 3, 5, 3, sandstoneSlab, sandstoneSlab, false);
this.addBlock(sandstone, 2, 5, 2);
BlockPos p1 = new BlockPos(2, 1, 2);
this.addBlock(water, p1.getX(), p1.getY(), p1.getZ());
Direction.Type.HORIZONTAL.forEach(facing -> {
BlockPos p2 = p1.offset(facing);
this.addBlock(water, p2.getX(), p2.getY(), p2.getZ());
});
}
public static List<Finder> create(World world, ChunkPos chunkPos) {
List<Finder> finders = new ArrayList<>();
finders.add(new DesertWellFinder(world, chunkPos));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z)));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x, chunkPos.z - 1)));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1)));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z)));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1)));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1)));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1)));
finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z + 1)));
return finders;
}
}
@@ -5,7 +5,6 @@ import kaptainwutax.seedcracker.cracker.population.DungeonData;
import kaptainwutax.seedcracker.finder.BlockFinder;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
import kaptainwutax.seedcracker.util.PosIterator;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
@@ -45,8 +44,6 @@ public class DungeonFinder extends BlockFinder {
//Gets all the positions with a mob spawner in the chunk.
List<BlockPos> result = super.findInChunk();
if(result.size() != 1)return new ArrayList<>();
result.removeIf(pos -> {
BlockEntity blockEntity = this.world.getBlockEntity(pos);
if(!(blockEntity instanceof MobSpawnerBlockEntity))return true;
@@ -72,10 +69,8 @@ public class DungeonFinder extends BlockFinder {
.map(pos -> this.getFloorCalls(this.getDungeonSize(pos), pos)).collect(Collectors.toList());
result.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new DungeonData(this.chunkPos, biome, starts.get(0), floorCallsList))) {
if(SeedCracker.get().onPopulationData(new DungeonData(this.chunkPos, biome, starts, floorCallsList))) {
this.renderers.add(new Cube(pos, new Vector4f(1.0f, 0.0f, 0.0f, 1.0f)));
Vec3i size = this.getDungeonSize(pos);
this.renderers.add(new Cuboid(pos.subtract(size), pos.add(size).add(1, -1, 1), new Vector4f(1.0f, 0.0f, 0.0f, 1.0f)));
}
});
@@ -86,7 +81,9 @@ public class DungeonFinder extends BlockFinder {
for(int xo = 4; xo >= 3; xo--) {
for(int zo = 4; zo >= 3; zo--) {
Block block = this.world.getBlockState(spawnerPos.add(xo, -1, zo)).getBlock();
if(block == Blocks.MOSSY_COBBLESTONE || block == Blocks.COBBLESTONE)return new Vec3i(xo, 0, zo);
if(block != Blocks.MOSSY_COBBLESTONE)continue;
if(block != Blocks.COBBLESTONE)continue;
return new Vec3i(xo, 0, zo);
}
}
@@ -1,6 +1,7 @@
package kaptainwutax.seedcracker.finder.population;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.DecoratorCache;
import kaptainwutax.seedcracker.cracker.population.EndGatewayData;
import kaptainwutax.seedcracker.finder.BlockFinder;
import kaptainwutax.seedcracker.finder.Finder;
@@ -13,6 +14,7 @@ import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.decorator.Decorator;
import java.util.ArrayList;
import java.util.List;
@@ -33,6 +35,10 @@ public class EndGatewayFinder extends BlockFinder {
//If no end gateway is supposed to populate in this chunk, return.
Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(8, 0, 8));
if(DecoratorCache.get().getSalt(biome, Decorator.END_GATEWAY, false) == DecoratorCache.INVALID) {
return new ArrayList<>();
}
List<BlockPos> result = super.findInChunk();
List<BlockPos> newResult = new ArrayList<>();
@@ -42,7 +48,7 @@ public class EndGatewayFinder extends BlockFinder {
if(height >= 3 && height <= 9) {
newResult.add(pos);
if(SeedCracker.get().getDataStorage().addBaseData(new EndGatewayData(this.chunkPos, biome, pos, height))) {
if(SeedCracker.get().onPopulationData(new EndGatewayData(this.chunkPos, biome, pos, height))) {
this.renderers.add(new Cuboid(pos.add(-1, -2, -1), pos.add(2, 3, 2), new Vector4f(0.4f, 0.4f, 0.82f, 1.0f)));
}
}
@@ -26,7 +26,7 @@ public class EndPillarsFinder extends Finder {
public EndPillarsFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos);
this.alreadyFound = !SeedCracker.get().getDataStorage().addPillarData(null);
this.alreadyFound = SeedCracker.get().onPillarData(null);
if(this.alreadyFound)return;
for(int i = 0; i < this.bedrockMarkers.length; i++) {
@@ -48,7 +48,7 @@ public class EndPillarsFinder extends Finder {
if(result.size() == this.bedrockMarkers.length) {
PillarData pillarData = new PillarData(result.stream().map(Vec3i::getY).collect(Collectors.toList()));
if(SeedCracker.get().getDataStorage().addPillarData(pillarData)) {
if(SeedCracker.get().onPillarData(pillarData)){
result.forEach(pos -> this.renderers.add(new Cube(pos, new Vector4f(0.5f, 0.0f, 0.5f, 1.0f))));
}
@@ -0,0 +1,42 @@
package kaptainwutax.seedcracker.finder.population.ore;
import kaptainwutax.seedcracker.finder.Finder;
import net.minecraft.block.Blocks;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import java.util.ArrayList;
import java.util.List;
public class DiamondOreFinder extends SimpleOreFinder {
public static OreFeatureConfig CONFIG = new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, Blocks.DIAMOND_ORE.getDefaultState(), 8);
protected static List<BlockPos> SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> {
if(pos.getY() > 16 + 4)return true;
return false;
});
public DiamondOreFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos, CONFIG);
this.searchPositions = SEARCH_POSITIONS;
}
@Override
public Vector4f getRenderColor() {
return new Vector4f(0.0f, 1.0f, 1.0f, 1.0f);
}
public static List<Finder> create(World world, ChunkPos chunkPos) {
List<Finder> finders = new ArrayList<>();
finders.add(new DiamondOreFinder(world, chunkPos));
finders.add(new DiamondOreFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z)));
finders.add(new DiamondOreFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1)));
finders.add(new DiamondOreFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1)));
return finders;
}
}
@@ -1,6 +1,7 @@
package kaptainwutax.seedcracker.finder.population.ore;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.DecoratorCache;
import kaptainwutax.seedcracker.cracker.population.EmeraldOreData;
import kaptainwutax.seedcracker.finder.BlockFinder;
import kaptainwutax.seedcracker.finder.Finder;
@@ -12,6 +13,7 @@ import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.decorator.Decorator;
import java.util.ArrayList;
import java.util.List;
@@ -19,8 +21,6 @@ import java.util.List;
public class EmeraldOreFinder extends BlockFinder {
protected static List<BlockPos> SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> {
if(pos.getY() < 4)return true;
if(pos.getY() > 28 + 4)return true;
return false;
});
@@ -33,11 +33,16 @@ public class EmeraldOreFinder extends BlockFinder {
public List<BlockPos> findInChunk() {
Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(8, 0, 8));
if(DecoratorCache.get().getSalt(biome, Decorator.EMERALD_ORE, false) == DecoratorCache.INVALID) {
return new ArrayList<>();
}
List<BlockPos> result = super.findInChunk();
if(!result.isEmpty() && SeedCracker.get().getDataStorage().addBaseData(new EmeraldOreData(this.chunkPos, biome, result))) {
//TODO: support more ores.
this.renderers.add(new Cube(result.get(0), new Vector4f(0.0f, 1.0f, 0.0f, 1.0f)));
if(!result.isEmpty() && SeedCracker.get().onPopulationData(new EmeraldOreData(this.chunkPos, biome, result))) {
result.forEach(pos -> {
this.renderers.add(new Cube(pos, new Vector4f(0.0f, 1.0f, 0.0f, 1.0f)));
});
}
return result;
@@ -0,0 +1,42 @@
package kaptainwutax.seedcracker.finder.population.ore;
import kaptainwutax.seedcracker.finder.Finder;
import net.minecraft.block.Blocks;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import java.util.ArrayList;
import java.util.List;
public class InfestedStoneOreFinder extends SimpleOreFinder {
public static OreFeatureConfig CONFIG = new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, Blocks.INFESTED_STONE.getDefaultState(), 9);
protected static List<BlockPos> SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> {
if(pos.getY() > 64 + 4)return true;
return false;
});
public InfestedStoneOreFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos, CONFIG);
this.searchPositions = SEARCH_POSITIONS;
}
@Override
public Vector4f getRenderColor() {
return new Vector4f(0.5f, 0.5f, 0.5f, 1.0f);
}
public static List<Finder> create(World world, ChunkPos chunkPos) {
List<Finder> finders = new ArrayList<>();
finders.add(new InfestedStoneOreFinder(world, chunkPos));
finders.add(new InfestedStoneOreFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z)));
finders.add(new InfestedStoneOreFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1)));
finders.add(new InfestedStoneOreFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1)));
return finders;
}
}
@@ -0,0 +1,50 @@
package kaptainwutax.seedcracker.finder.population.ore;
import kaptainwutax.seedcracker.finder.population.OreFinder;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public abstract class SimpleOreFinder extends OreFinder {
public SimpleOreFinder(World world, ChunkPos chunkPos, OreFeatureConfig oreFeatureConfig) {
super(world, chunkPos, oreFeatureConfig);
}
@Override
public void findOreVeins(List<Set<BlockPos>> veins) {
List<BlockPos> starts = new ArrayList<>();
for(Set<BlockPos> vein: veins) {
//This is a semi-accurate estimate.
BlockPos oreStart = new BlockPos(
this.findX(vein, OreFinder.HIGHEST),
this.findY(vein, OreFinder.LOWEST) + 2,
this.findZ(vein, OreFinder.HIGHEST)
);
starts.add(oreStart);
}
//If the start overlaps with another chunk, get rid of it.
starts.removeIf(start -> {
if((start.getX() & 15) == 0 || (start.getX() & 15) == 15)return true;
if((start.getZ() & 15) == 0 || (start.getZ() & 15) == 15)return true;
return false;
});
starts.forEach(start -> {
this.renderers.add(new Cuboid(start.add(-1, -1, -1), start.add(1, 0, 1), this.getRenderColor()));
});
}
public abstract Vector4f getRenderColor();
}
@@ -1,19 +0,0 @@
package kaptainwutax.seedcracker.finder.profile;
public class CustomProfile extends FinderProfile {
public CustomProfile() {
super(false);
this.author = "";
this.locked = false;
}
public void setAuthor(String author) {
this.author = author;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
}
@@ -1,34 +0,0 @@
package kaptainwutax.seedcracker.finder.profile;
import kaptainwutax.seedcracker.finder.Finder;
import java.util.HashMap;
public abstract class FinderProfile {
public final HashMap<Finder.Type, Boolean> typeStates = new HashMap<>();
protected String author;
protected boolean locked;
public FinderProfile(boolean defaultState) {
for(Finder.Type type: Finder.Type.values()) {
this.typeStates.put(type, defaultState);
}
}
public String getAuthor() {
return this.author;
}
public boolean getLocked() {
return this.locked;
}
public boolean setTypeState(Finder.Type type, boolean state) {
if(this.getLocked())return false;
this.typeStates.put(type, state);
return true;
}
}
@@ -1,11 +0,0 @@
package kaptainwutax.seedcracker.finder.profile;
public class NopeProfile extends FinderProfile {
public NopeProfile() {
super(false);
this.author = "KaptainWutax";
this.locked = true;
}
}
@@ -1,11 +0,0 @@
package kaptainwutax.seedcracker.finder.profile;
public class VanillaProfile extends FinderProfile {
public VanillaProfile() {
super(true);
this.author = "KaptainWutax";
this.locked = true;
}
}
@@ -1,9 +1,6 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
@@ -57,12 +54,6 @@ public abstract class AbstractTempleFinder extends Finder {
protected abstract StructureFeature<?> getStructureFeature();
public void addRenderers(PieceFinder pieceFinder, BlockPos origin, Vector4f color) {
this.renderers.add(new Cuboid(origin, pieceFinder.getLayout(), color));
BlockPos chunkStart = new BlockPos(origin.getX() & -16, origin.getY(), origin.getZ() & -16);
this.renderers.add(new Cube(chunkStart, color));
}
public Map<PieceFinder, List<BlockPos>> findInChunkPieces() {
Map<PieceFinder, List<BlockPos>> result = new HashMap<>();
@@ -1,8 +1,7 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.BlockFinder;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
@@ -27,7 +26,7 @@ public class BuriedTreasureFinder extends BlockFinder {
int localX = pos.getX() & 15;
int localZ = pos.getZ() & 15;
if(localX != 9 || localZ != 9)return true;
if(pos.getY() > 90)return true;
return false;
});
@@ -56,23 +55,28 @@ public class BuriedTreasureFinder extends BlockFinder {
@Override
public List<BlockPos> findInChunk() {
Biome biome = world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9));
if(!biome.hasStructureFeature(Feature.BURIED_TREASURE))return new ArrayList<>();
//Gets all the positions with a chest in the chunk.
List<BlockPos> result = super.findInChunk();
result.removeIf(pos -> {
//Chest can't be waterlogged!
BlockState chest = world.getBlockState(pos);
if(chest.get(ChestBlock.WATERLOGGED))return true;
//Only so many blocks can hold a treasure chest.
BlockState chestHolder = world.getBlockState(pos.down());
if(!CHEST_HOLDERS.contains(chestHolder))return true;
//Check if the biome contains the buried treasure feature.
Biome biome = world.getBiome(pos);
if(!biome.hasStructureFeature(Feature.BURIED_TREASURE))return true;
//Damn that chest be lucky!
return false;
});
result.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(this.chunkPos, StructureFeatures.BURIED_TREASURE))) {
if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.BURIED_TREASURE))) {
this.renderers.add(new Cube(pos, new Vector4f(1.0f, 1.0f, 0.0f, 1.0f)));
}
});
@@ -1,9 +1,9 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.StairsBlock;
@@ -35,8 +35,8 @@ public class DesertTempleFinder extends AbstractTempleFinder {
combinedResult.addAll(positions);
positions.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(this.chunkPos, StructureFeatures.DESERT_PYRAMID))) {
this.addRenderers(pieceFinder, pos, new Vector4f(1.0f, 0.0f, 1.0f, 1.0f));
if( SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.DESERT_PYRAMID))) {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f)));
}
});
});
@@ -1,8 +1,7 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
@@ -14,9 +13,7 @@ import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.feature.Feature;
import java.util.ArrayList;
import java.util.HashMap;
@@ -26,7 +23,6 @@ import java.util.Map;
public class EndCityFinder extends Finder {
protected static List<BlockPos> SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> {
if(pos.getY() > 90)return true;
return false;
});
@@ -77,12 +73,6 @@ public class EndCityFinder extends Finder {
@Override
public List<BlockPos> findInChunk() {
Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9));
if(!biome.hasStructureFeature(Feature.END_CITY)) {
return new ArrayList<>();
}
Map<PieceFinder, List<BlockPos>> result = this.findInChunkPieces();
List<BlockPos> combinedResult = new ArrayList<>();
@@ -95,7 +85,7 @@ public class EndCityFinder extends Finder {
combinedResult.addAll(positions);
positions.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(this.chunkPos, StructureFeatures.END_CITY))) {
if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.END_CITY))) {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.6f, 0.0f, 0.6f, 1.0f)));
this.renderers.add(new Cube(pos, new Vector4f(0.6f, 0.0f, 0.6f, 1.0f)));
}
@@ -1,8 +1,7 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
@@ -45,7 +44,7 @@ public class IglooFinder extends AbstractTempleFinder {
combinedResult.addAll(positions);
positions.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(this.chunkPos, StructureFeatures.IGLOO))) {
if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.IGLOO))) {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.0f, 1.0f, 1.0f, 1.0f)));
this.renderers.add(new Cube(pos, new Vector4f(0.0f, 1.0f, 1.0f, 1.0f)));
}
@@ -1,9 +1,9 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.*;
import net.minecraft.block.enums.WallMountLocation;
import net.minecraft.block.enums.WireConnection;
@@ -35,8 +35,8 @@ public class JungleTempleFinder extends AbstractTempleFinder {
combinedResult.addAll(positions);
positions.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(this.chunkPos, StructureFeatures.JUNGLE_TEMPLE))) {
this.addRenderers(pieceFinder, pos, new Vector4f(1.0f, 0.0f, 1.0f, 1.0f));
if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.JUNGLE_TEMPLE))) {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f)));
}
});
});
@@ -1,8 +1,7 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
@@ -14,9 +13,7 @@ import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.feature.Feature;
import java.util.ArrayList;
import java.util.HashMap;
@@ -26,6 +23,7 @@ import java.util.Map;
public class MansionFinder extends Finder {
protected static List<BlockPos> SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> {
if(pos.getY() != 64)return true;
if((pos.getX() & 15) != 0)return true;
if((pos.getZ() & 15) != 0)return true;
return false;
@@ -37,32 +35,31 @@ public class MansionFinder extends Finder {
public MansionFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos);
for(Direction direction: Direction.values()) {
PieceFinder finder = new PieceFinder(world, chunkPos, direction, this.size);
Direction.Type.HORIZONTAL.forEach(direction -> {
PieceFinder finder = new PieceFinder(world, chunkPos, direction, size);
finder.searchPositions = SEARCH_POSITIONS;
buildStructure(finder);
this.finders.add(finder);
}
});
}
@Override
public List<BlockPos> findInChunk() {
Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9));
if(!biome.hasStructureFeature(Feature.WOODLAND_MANSION)) {
return new ArrayList<>();
}
Map<PieceFinder, List<BlockPos>> result = this.findInChunkPieces();
List<BlockPos> combinedResult = new ArrayList<>();
result.forEach((pieceFinder, positions) -> {
positions.removeIf(pos -> {
//Figure this out, it's not a trivial task.
return false;
});
combinedResult.addAll(positions);
positions.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(this.chunkPos, StructureFeatures.WOODLAND_MANSION))) {
if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.WOODLAND_MANSION))) {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.4f, 0.26f, 0.13f, 1.0f)));
this.renderers.add(new Cube(this.chunkPos.getCenterBlockPos().add(0, pos.getY(), 0), new Vector4f(0.4f, 0.26f, 0.13f, 1.0f)));
}
@@ -83,26 +80,12 @@ public class MansionFinder extends Finder {
}
public void buildStructure(PieceFinder finder) {
BlockState air = Blocks.AIR.getDefaultState();
BlockState cobblestone = Blocks.COBBLESTONE.getDefaultState();
BlockState birchPlanks = Blocks.BIRCH_PLANKS.getDefaultState();
BlockState redCarpet = Blocks.RED_CARPET.getDefaultState();
BlockState whiteCarpet = Blocks.WHITE_CARPET.getDefaultState();
finder.fillWithOutline(0, 0, 0, 15, 0, 15, birchPlanks, birchPlanks, false);
finder.fillWithOutline(0, 0, 8, 6, 0, 12, null, null, false);
finder.fillWithOutline(0, 0, 12, 9, 0, 15, null, null, false);
finder.fillWithOutline(15, 0, 0, 15, 0, 15, cobblestone, cobblestone, false);
finder.addBlock(Blocks.DARK_OAK_LOG.getDefaultState(), 15, 0, 15);
finder.addBlock(Blocks.DARK_OAK_LOG.getDefaultState(), 15, 0, 7);
finder.addBlock(Blocks.DARK_OAK_LOG.getDefaultState(), 14, 0, 7);
finder.fillWithOutline(9, 1, 0, 9, 1, 8, whiteCarpet, whiteCarpet, false);
finder.addBlock(whiteCarpet, 8,1, 8);
finder.fillWithOutline(13, 1, 0, 13, 1, 8, whiteCarpet, whiteCarpet, false);
finder.addBlock(whiteCarpet, 14,1, 8);
finder.fillWithOutline(10, 1, 0, 12, 1, 15, redCarpet, redCarpet, false);
//TODO: Finish this.
}
@Override
@@ -1,8 +1,7 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
@@ -58,7 +57,7 @@ public class OceanMonumentFinder extends Finder {
positions.forEach(pos -> {
ChunkPos monumentStart = new ChunkPos(this.chunkPos.x + 1, this.chunkPos.z + 1);
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(monumentStart, StructureFeatures.OCEAN_MONUMENT))) {
if(SeedCracker.get().onStructureData(new StructureData(monumentStart, StructureData.OCEAN_MONUMENT))) {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.0f, 0.0f, 1.0f, 1.0f)));
this.renderers.add(new Cube(monumentStart.getCenterBlockPos().add(0, pos.getY(), 0), new Vector4f(0.0f, 0.0f, 1.0f, 1.0f)));
}
@@ -18,7 +18,7 @@ import java.util.Map;
public class PieceFinder extends Finder {
protected Map<BlockPos, BlockState> structure = new LinkedHashMap<>();
private BlockBox boundingBox;
private MutableIntBoundingBox boundingBox;
protected List<BlockPos> searchPositions = new ArrayList<>();
protected Direction facing;
@@ -40,12 +40,12 @@ public class PieceFinder extends Finder {
this.depth = size.getZ();
if(this.facing.getAxis() == Direction.Axis.Z) {
this.boundingBox = new BlockBox(
this.boundingBox = new MutableIntBoundingBox(
0, 0, 0,
size.getX() - 1, size.getY() - 1, size.getZ() - 1
);
} else {
this.boundingBox = new BlockBox(
this.boundingBox = new MutableIntBoundingBox(
0, 0, 0,
size.getZ() - 1, size.getY() - 1, size.getX() - 1
);
@@ -71,7 +71,7 @@ public class PieceFinder extends Finder {
//FOR DEBUGGING PIECES.
if(this.debug) {
MinecraftClient.getInstance().execute(() -> {
int y = this.rotation.ordinal() * 10 + this.mirror.ordinal() * 20 + 120;
int y = this.rotation.ordinal() * 10 + this.mirror.ordinal() * 20 + 100;
if (this.chunkPos.x % 2 == 0 && this.chunkPos.z % 2 == 0) {
this.structure.forEach((pos, state) -> {
@@ -89,7 +89,7 @@ public class PieceFinder extends Finder {
BlockState state = this.world.getBlockState(pos);
//Blockstate may change when it gets placed in the world, that's why it's using the block here.
if(entry.getValue() != null && !state.getBlock().equals(entry.getValue().getBlock())) {
if(!state.getBlock().equals(entry.getValue().getBlock())) {
found = false;
break;
}
@@ -200,6 +200,10 @@ public class PieceFinder extends Finder {
}
protected void addBlock(BlockState state, int x, int y, int z) {
if(state == null) {
return;
}
BlockPos pos = new BlockPos(
this.applyXTransform(x, z),
this.applyYTransform(y),
@@ -207,11 +211,6 @@ public class PieceFinder extends Finder {
);
if(this.boundingBox.contains(pos)) {
if(state == null) {
this.structure.remove(pos);
return;
}
if (this.mirror != BlockMirror.NONE) {
state = state.mirror(this.mirror);
}
@@ -220,7 +219,6 @@ public class PieceFinder extends Finder {
state = state.rotate(this.rotation);
}
this.structure.put(pos, state);
}
}
@@ -1,211 +0,0 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.finder.BlockFinder;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cube;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.block.enums.ChestType;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.feature.Feature;
import java.util.ArrayList;
import java.util.List;
public class ShipwreckFinder extends BlockFinder {
protected static List<BlockPos> SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> {
return false;
});
public ShipwreckFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos, Blocks.CHEST);
this.searchPositions = SEARCH_POSITIONS;
}
@Override
public List<BlockPos> findInChunk() {
Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9));
if(!biome.hasStructureFeature(Feature.SHIPWRECK)) {
return new ArrayList<>();
}
List<BlockPos> result = super.findInChunk();
result.removeIf(pos -> {
BlockState state = this.world.getBlockState(pos);
if(state.get(ChestBlock.CHEST_TYPE) != ChestType.SINGLE)return true;
BlockEntity blockEntity = this.world.getBlockEntity(pos);
if(!(blockEntity instanceof ChestBlockEntity))return true;
return !this.onChestFound(pos);
});
return result;
}
/**
* Source: https://github.com/skyrising/casual-mod/blob/master/src/main/java/de/skyrising/casual/ShipwreckFinder.java
* */
private boolean onChestFound(BlockPos pos) {
BlockPos.Mutable mutablePos = new BlockPos.Mutable(pos);
Direction chestFacing = world.getBlockState(pos).get(ChestBlock.FACING);
int[] stairs = new int[4];
int totalStairs = 0;
int[] trapdoors = new int[4];
int totalTrapdoors = 0;
for(int y = -1; y <= 2; y++) {
for(int x = -1; x <= 1; x++) {
for(int z = -1; z <= 1; z++) {
if (x == 0 && y == 0 && z == 0)continue;
mutablePos.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z);
BlockState neighborState = world.getBlockState(mutablePos);
Block neighborBlock = neighborState.getBlock();
if(neighborBlock == Blocks.VOID_AIR)return false;
if(neighborBlock instanceof StairsBlock) {
stairs[y + 1]++;
totalStairs++;
} else if(neighborBlock instanceof TrapdoorBlock) {
trapdoors[y + 1]++;
totalTrapdoors++;
}
}
}
}
//System.out.printf("%s: chest facing %s\n", pos, chestFacing);
int chestX = 4;
int chestY = 2;
int chestZ = 0;
int length = 16;
int height = 9;
Direction direction = chestFacing;
if(trapdoors[3] > 4) { // with_mast[_degraded]
chestZ = 9;
height = 21;
length = 28;
} else if(totalTrapdoors == 0 && stairs[3] == 3) { // upsidedown_backhalf[_degraded]
if(stairs[0] == 0) {
chestX = 2;
chestZ = 12;
direction = chestFacing.getOpposite();
} else { // redundant
chestX = 3;
chestY = 5;
chestZ = 5;
direction = chestFacing.rotateYClockwise();
}
} else if(totalTrapdoors == 0) { // rightsideup that have backhalf
if(stairs[0] == 4) {
if(totalStairs > 4) {
chestX = 6;
chestY = 4;
chestZ = 12;
direction = chestFacing.getOpposite();
} else { // sideways backhalf
chestX = 6;
chestY = 3;
chestZ = 8;
length = 17;
direction = chestFacing.getOpposite();
}
} else if(stairs[0] == 3 && totalStairs > 5) {
chestX = 5;
chestZ = 6;
direction = chestFacing.rotateYCounterclockwise();
}
mutablePos.set(pos);
mutablePos.setOffset(0, -chestY, 0);
mutablePos.setOffset(direction.rotateYClockwise(), chestX - 4);
mutablePos.setOffset(direction, -chestZ - 1);
if(this.world.getBlockState(mutablePos).getMaterial() == Material.WOOD) {
if(length == 17) { // sideways
chestZ += 11;
length += 11;
} else {
chestZ += 12;
length += 12;
}
mutablePos.setOffset(0, 10, 0);
if(this.world.getBlockState(mutablePos).getBlock() instanceof LogBlock) {
height = 21;
}
}
} else if(totalTrapdoors == 2 && trapdoors[3] == 2 && stairs[3] == 3) { // rightsideup_fronthalf[_degraded]
chestZ = 8;
length = 24;
}
if(chestZ != 0) {
mutablePos.set(pos);
mutablePos.setOffset(direction, 15 - chestZ);
mutablePos.setOffset(direction.rotateYClockwise(), chestX - 4);
BlockPos.Mutable pos2 = new BlockPos.Mutable(mutablePos);
pos2.setOffset(0, -chestY, 0);
pos2.setOffset(direction, -15);
pos2.setOffset(direction.rotateYClockwise(), 4);
BlockPos.Mutable pos3 = new BlockPos.Mutable(pos2);
pos3.setOffset(direction, length - 1);
pos3.setOffset(direction.rotateYClockwise(), -8);
pos3.setOffset(0, height - 1, 0);
BlockBox box = new BlockBox(
Math.min(pos2.getX(), pos3.getX()), pos2.getY(), Math.min(pos2.getZ(), pos3.getZ()),
Math.max(pos2.getX(), pos3.getX()) + 1, pos3.getY() + 1, Math.max(pos2.getZ(), pos3.getZ()) + 1);
mutablePos.setOffset(-4, -chestY, -15);
if((mutablePos.getX() & 0xf) == 0 && (mutablePos.getZ() & 0xf) == 0) {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(new ChunkPos(mutablePos), StructureFeatures.SHIPWRECK))) {
this.renderers.add(new Cuboid(box, new Vector4f(0.0f, 1.0f, 1.0f, 1.0f)));
this.renderers.add(new Cube(new ChunkPos(mutablePos).getCenterBlockPos().offset(Direction.UP, mutablePos.getY()), new Vector4f(0.0f, 1.0f, 1.0f, 1.0f)));
return true;
}
}
}
return false;
}
@Override
public boolean isValidDimension(DimensionType dimension) {
return dimension == DimensionType.OVERWORLD;
}
public static List<Finder> create(World world, ChunkPos chunkPos) {
List<Finder> finders = new ArrayList<>();
finders.add(new ShipwreckFinder(world, chunkPos));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z)));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x, chunkPos.z - 1)));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1)));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z)));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1)));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1)));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1)));
finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z + 1)));
return finders;
}
}
@@ -1,9 +1,9 @@
package kaptainwutax.seedcracker.finder.structure;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.structure.StructureData;
import kaptainwutax.seedcracker.cracker.structure.StructureFeatures;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.finder.Finder;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.StairsBlock;
@@ -36,8 +36,8 @@ public class SwampHutFinder extends AbstractTempleFinder {
combinedResult.addAll(positions);
positions.forEach(pos -> {
if(SeedCracker.get().getDataStorage().addBaseData(new StructureData(this.chunkPos, StructureFeatures.SWAMP_HUT))) {
this.addRenderers(pieceFinder, pos, new Vector4f(1.0f, 0.0f, 1.0f, 1.0f));
if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.SWAMP_HUT))) {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f)));
}
});
});
@@ -1,46 +0,0 @@
package kaptainwutax.seedcracker.gui;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
import io.github.cottonmc.cotton.gui.widget.WButton;
import io.github.cottonmc.cotton.gui.widget.WGridPanel;
import io.github.cottonmc.cotton.gui.widget.WLabel;
import io.github.cottonmc.cotton.gui.widget.WSprite;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.finder.FinderQueue;
import net.minecraft.text.LiteralText;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Identifier;
public class Gui extends LightweightGuiDescription {
public Gui() {
WGridPanel root = new WGridPanel();
setRootPanel(root);
root.setSize(256, 240);
WSprite icon = new WSprite(new Identifier("minecraft:textures/item/redstone.png"));
root.add(icon, 0, 2, 1, 1);
WButton button = new WButton(new TranslatableText("RESET DATA"));
button.setOnClick(new Runnable() {
@Override
public void run() {
SeedCracker.get().getDataStorage().clear();
FinderQueue.get().clear();
}
}
);
root.add(button, 0, 3, 4, 1);
WLabel label = new WLabel(new LiteralText("Test"), 0xFFFFFF);
root.add(label, 0, 4, 2, 1);
root.validate(this);
}
@Override
public void addPainters() {
getRootPanel().setBackgroundPainter(BackgroundPainter.VANILLA); //This is done automatically though
}
}
@@ -1,22 +0,0 @@
package kaptainwutax.seedcracker.gui;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
public class GuiItem extends Item {
public GuiItem(Settings settings) {
super(settings);
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
MinecraftClient.getInstance().openScreen(new Screen(new Gui()));
return super.use(world, user, hand);
}
}
@@ -1,11 +0,0 @@
package kaptainwutax.seedcracker.gui;
import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.client.CottonClientScreen;
public class Screen extends CottonClientScreen {
public Screen(GuiDescription description) {
super(description);
}
}
@@ -1,43 +0,0 @@
package kaptainwutax.seedcracker.init;
import kaptainwutax.seedcracker.util.Log;
import net.minecraft.client.options.KeyBinding;
import java.util.LinkedHashSet;
public class KeyBindings {
public static LinkedHashSet<KeyBinding> KEY_REGISTRY = new LinkedHashSet<>();
public static LinkedHashSet<String> CATEGORY_REGISTRY = new LinkedHashSet<>();
public static KeyBinding OPEN_MENU = new KeyBinding(getName("open_menu"), 'M', getCategory("seedcracker"));
static {
registerKeyBinding(OPEN_MENU);
}
/*
* Registers keys and their categories. Remember that everything is FIFO.
*/
private static void registerKeyBinding(KeyBinding keyBinding) {
if(keyBinding == null) {
throw new NullPointerException("Cannot register a null key binding!");
} else {
KEY_REGISTRY.add(keyBinding);
CATEGORY_REGISTRY.add(keyBinding.getCategory());
Log.debug("Registering key [" + keyBinding.getName() + ", " + keyBinding.getId() + "] from category [" + keyBinding.getCategory() + "].");
}
}
/*
* Generates the category and key prefixes for the language files.
*/
public static String getCategory(String registryName) {
return "key.categories." + registryName;
}
public static String getName(String registryName) {
return "key." + registryName.toLowerCase();
}
}
@@ -1,41 +0,0 @@
package kaptainwutax.seedcracker.magic;
/**
* Math utility library-- I have no idea how it works, don't ask.
* All credits to Matthew. (The man doesn't have a GitHub, shame!)
* */
public class MagicMath {
public static final long MASK_16 = 0xFFFFL;
public static final long MASK_32 = 0xFFFF_FFFFL;
public static final long MASK_48 = 0xFFFF_FFFF_FFFFL;
public static int countTrailingZeroes(long v) {
int c; // output: c will count v's trailing zero bits,
// so if v is 1101000 (base 2), then c will be 3
v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest
for(c = 0; v != 0; c++) {
v >>>= 1;
}
return c;
}
public static long modInverse(long x, int mod) { //Fast method for modular inverse mod powers of 2
long inv = 0;
long b = 1;
for(int i = 0; i < mod; i++) {
if((b & 1) == 1) {
inv |= 1L << i;
b = (b - x) >> 1;
} else {
b >>= 1;
}
}
return inv;
}
}
@@ -1,122 +0,0 @@
package kaptainwutax.seedcracker.magic;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.Seeds;
import kaptainwutax.seedcracker.util.math.LCG;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class PopulationReversal {
private static final LCG SKIP_2 = Rand.JAVA_LCG.combine(2);
private static final LCG SKIP_4 = Rand.JAVA_LCG.combine(4);
public static ArrayList<Long> getWorldSeeds(long populationSeed, int x, int z) {
populationSeed ^= Rand.JAVA_LCG.multiplier;
ArrayList<Long> worldSeeds = new ArrayList<>();
if (x == 0 && z == 0) {
worldSeeds.add(populationSeed);
return worldSeeds;
}
long c; //a is upper 16 bits, b middle 16 bits, c lower 16 bits of worldseed.
long e = populationSeed & MagicMath.MASK_32; //The algorithm proceeds by solving for worldseed in 16 bit groups
long f = populationSeed & MagicMath.MASK_16; //as such, we need the 16 bit groups of chunkseed for later eqns.
boolean xEven = (x & 1) == 0;
boolean zEven = (z & 1) == 0;
long firstMultiplier = (SKIP_2.multiplier * x + SKIP_4.multiplier * z) & MagicMath.MASK_16;
int multTrailingZeroes = MagicMath.countTrailingZeroes(firstMultiplier); //TODO currently code blows up if this is 16, but you can use it to get bits of seed anyway if it is non zero
long firstMultInv = MagicMath.modInverse(firstMultiplier >> multTrailingZeroes,16);
//TODO We can recover more initial bits when x + z is divisible by a power of 2
if (xEven ^ zEven) { //bottom bit of x*a + z*b is odd so we xor by 1 to get bottom bit of worldseed.
c = (populationSeed & 1) ^ 1;
} else { //bottom bit of x*a + z*b is even so we xor by 0 to get bottom bit of worldseed.
c = (populationSeed & 1);
}
for (; c < (1L << 16); c += 2) { //iterate through all possible lower 16 bits of worldseed.
long target = (c ^ f) & MagicMath.MASK_16; //now that we've guessed 16 bits of worldseed we can undo the mask
//We need to handle the four different cases of the effect the two | 1s have on the seed
long magic = x * ((SKIP_2.multiplier * ((c ^ Rand.JAVA_LCG.multiplier) & MagicMath.MASK_16) + SKIP_2.addend) >>> 16) + z * ((SKIP_4.multiplier * ((c ^ Rand.JAVA_LCG.multiplier) & MagicMath.MASK_16) + SKIP_4.addend) >>> 16);
addWorldSeed(worldSeeds, target - (magic & MagicMath.MASK_16), multTrailingZeroes, firstMultInv, c, e, x, z, populationSeed); //case both nextLongs were odd
addWorldSeed(worldSeeds, target - ((magic + x) & MagicMath.MASK_16), multTrailingZeroes, firstMultInv, c, e, x, z, populationSeed); //case where x nextLong even
addWorldSeed(worldSeeds, target - ((magic + z) & MagicMath.MASK_16), multTrailingZeroes, firstMultInv, c, e, x, z, populationSeed); //case where z nextLong even
addWorldSeed(worldSeeds, target - ((magic + x + z) & MagicMath.MASK_16), multTrailingZeroes, firstMultInv, c, e, x, z, populationSeed); //case where both nextLongs even
}
return worldSeeds;
}
public static long makeSecondAddend(int x, long k, int z) {
return ((x*((((SKIP_2.multiplier * ((k ^ Rand.JAVA_LCG.multiplier) & MagicMath.MASK_32) + SKIP_2.addend) & MagicMath.MASK_48) >>> 16) | 1L) +
z*((((SKIP_4.multiplier * ((k ^ Rand.JAVA_LCG.multiplier) & MagicMath.MASK_32) + SKIP_4.addend) & MagicMath.MASK_48) >>> 16) | 1L)) >>> 16) & MagicMath.MASK_16;
}
public static void addWorldSeed(List<Long> worldSeeds, long firstAddend, int multTrailingZeroes, long firstMultInv, long c, long e, int x, int z, long populationSeed){
if(MagicMath.countTrailingZeroes(firstAddend) >= multTrailingZeroes) { //Does there exist a set of 16 bits which work for bits 17-32
long b = ((((firstMultInv * firstAddend)>>> multTrailingZeroes) ^ (Rand.JAVA_LCG.multiplier >> 16)) & ((1L << (16 - multTrailingZeroes)) - 1));
for(; b < (1L << 16); b += (1L << (16 - multTrailingZeroes))) { //if the previous multiplier had a power of 2 divisor, we get multiple solutions for b
long k = (b << 16) + c;
long target2 = (k ^ e) >> 16; //now that we know b, we can undo more of the mask
long secondAddend = makeSecondAddend(x, k, z);
if (MagicMath.countTrailingZeroes(target2 - secondAddend) >= multTrailingZeroes) { //Does there exist a set of 16 bits which work for bits 33-48
long a = ((((firstMultInv * (target2 - secondAddend)) >>> multTrailingZeroes) ^ (Rand.JAVA_LCG.multiplier >> 32)) & ((1L << (16-multTrailingZeroes)) - 1));
for(; a < (1L << 16); a += (1L << (16 - multTrailingZeroes))) { //if the previous multiplier had a power of 2 divisor, we get multiple solutions for a
if(Seeds.setPopulationSeed(null, (a << 32) + k, x, z) == populationSeed) { //lazy check if the test has succeeded
worldSeeds.add((a << 32) + k);
}
}
}
}
}
}
/*
* Left as reference if I need to test this mess again. :P
* */
public static void main(String[] args) {
long seed;
int x , z;
ArrayList<Long> seeds;
/*long seed = 40820992642153L;
int x = 2;
int z = 4;
ArrayList<Long> seeds = getSeedFromChunkseed(getChunkseed(seed, x, z), x, z);
System.out.println("start");
for (long a : seeds) {
System.out.println(a);
}
System.out.println("done");*/
Random r = new Random();
int failcount = 0;
System.out.println("start");
long start = System.currentTimeMillis();
for(int i = 0; i < 100000; i++){
seed = r.nextLong() & ((1L << 48)-1);
x = r.nextInt(16) - 8;
z = r.nextInt(16) - 8;
seeds = getWorldSeeds(Seeds.setPopulationSeed(null, seed, x, z) ^ Rand.JAVA_LCG.multiplier, x, z);
if (!seeds.contains(seed)) {
System.out.println(seed);
System.out.println(x);
System.out.println(z);
failcount++;
System.out.println();
}
}
System.out.println("End: "+((System.currentTimeMillis()-start)/1000.0));
System.out.println(failcount+" failures.");
}
}
@@ -1,23 +0,0 @@
package kaptainwutax.seedcracker.magic;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.math.LCG;
public class RandomSeed {
private static final LCG INVERSE_LCG = Rand.JAVA_LCG.combine(-1);
/**
* Source: https://twitter.com/Geosquare_/status/1169623192153010176
* */
public static boolean isRandomSeed(long worldSeed) {
long upperBits = worldSeed >>> 32;
long lowerBits = worldSeed & MagicMath.MASK_32;
long a = (24667315 * upperBits + 18218081 * lowerBits + 67552711) >> 32;
long b = (-4824621 * upperBits + 7847617 * lowerBits + 7847617) >> 32;
long seed = INVERSE_LCG.nextSeed(7847617 * a - 18218081 * b);
return new Rand(seed, false).nextLong() == worldSeed;
}
}
@@ -2,16 +2,13 @@ package kaptainwutax.seedcracker.mixin;
import com.mojang.authlib.GameProfile;
import com.mojang.brigadier.CommandDispatcher;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.init.ClientCommands;
import kaptainwutax.seedcracker.cracker.storage.HashedSeedData;
import kaptainwutax.seedcracker.command.ClientCommands;
import kaptainwutax.seedcracker.finder.FinderQueue;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.packet.ChunkDataS2CPacket;
import net.minecraft.client.network.packet.CommandTreeS2CPacket;
import net.minecraft.client.network.packet.PlayerRespawnS2CPacket;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.network.ClientConnection;
import net.minecraft.server.command.CommandSource;
@@ -36,7 +33,6 @@ public abstract class ClientPlayNetworkHandlerMixin {
FinderQueue.get().onChunkData(this.world, new ChunkPos(chunkX, chunkZ));
}
@SuppressWarnings("unchecked")
@Inject(method = "<init>", at = @At("RETURN"))
public void onInit(MinecraftClient mc, Screen screen, ClientConnection connection, GameProfile profile, CallbackInfo ci) {
ClientCommands.registerCommands((CommandDispatcher<ServerCommandSource>)(Object)this.commandDispatcher);
@@ -48,9 +44,4 @@ public abstract class ClientPlayNetworkHandlerMixin {
ClientCommands.registerCommands((CommandDispatcher<ServerCommandSource>)(Object)this.commandDispatcher);
}
@Inject(method = "onPlayerRespawn", at = @At("HEAD"))
public void onPlayerRespawn(PlayerRespawnS2CPacket packet, CallbackInfo ci) {
SeedCracker.get().getDataStorage().addHashedSeedData(new HashedSeedData(packet.method_22425()));
}
}
@@ -1,8 +1,7 @@
package kaptainwutax.seedcracker.mixin;
import com.mojang.brigadier.StringReader;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.init.ClientCommands;
import kaptainwutax.seedcracker.command.ClientCommands;
import net.minecraft.client.network.ClientPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -14,11 +13,6 @@ import java.util.regex.Pattern;
@Mixin(ClientPlayerEntity.class)
public abstract class ClientPlayerEntityMixin {
@Inject(method = "tick", at = @At("HEAD"))
private void tick(CallbackInfo ci) {
SeedCracker.get().getDataStorage().tick();
}
@Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true)
private void onSendChatMessage(String message, CallbackInfo ci) {
if(message.startsWith("/")) {
@@ -1,28 +1,24 @@
package kaptainwutax.seedcracker.mixin;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.finder.FinderQueue;
import kaptainwutax.seedcracker.SeedCracker;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.concurrent.Executors;
@Mixin(ClientWorld.class)
public abstract class ClientWorldMixin {
@Inject(method = "disconnect", at = @At("HEAD"))
@Inject(method = "disconnect", at = @At("TAIL"))
private void disconnect(CallbackInfo ci) {
SeedCracker.get().getDataStorage().clear();
SeedCracker.get().clear();
FinderQueue.get().clear();
}
@Inject(method = "getGeneratorStoredBiome", at = @At("HEAD"), cancellable = true)
private void getGeneratorStoredBiome(int x, int y, int z, CallbackInfoReturnable<Biome> ci) {
ci.setReturnValue(Biomes.THE_VOID);
FinderQueue.SERVICE.shutdown();
FinderQueue.SERVICE = Executors.newFixedThreadPool(5);
}
}
@@ -1,36 +0,0 @@
package kaptainwutax.seedcracker.mixin;
import kaptainwutax.seedcracker.init.KeyBindings;
import net.minecraft.client.options.GameOptions;
import net.minecraft.client.options.KeyBinding;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Iterator;
@Mixin(GameOptions.class)
public class GameOptionsMixin {
@Shadow public KeyBinding[] keysAll;
@Inject(method = "<init>", at = @At("RETURN"))
private void init(CallbackInfo ci) {
KeyBinding[] oldKeys = this.keysAll;
KeyBinding[] newKeys = new KeyBinding[oldKeys.length + KeyBindings.KEY_REGISTRY.size()];
Iterator<KeyBinding> keyBindingIterator = KeyBindings.KEY_REGISTRY.iterator();
for(int i = 0; i < newKeys.length; i++) {
if(i < oldKeys.length) {
newKeys[i] = oldKeys[i];
} else {
newKeys[i] = keyBindingIterator.next();
}
}
this.keysAll = newKeys;
}
}
@@ -2,7 +2,6 @@ package kaptainwutax.seedcracker.mixin;
import kaptainwutax.seedcracker.render.RenderQueue;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -11,14 +10,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GameRenderer.class)
public abstract class GameRendererMixin {
@Inject(method = "renderWorld", at = @At("HEAD"))
private void renderWorldStart(float delta, long time, MatrixStack matrixStack, CallbackInfo ci) {
RenderQueue.get().setTrackRender(matrixStack);
@Inject(method = "renderCenter", at = @At("HEAD"))
private void renderCenterStart(float delta, long time, CallbackInfo ci) {
RenderQueue.get().setTrackRender(true);
}
@Inject(method = "renderWorld", at = @At("TAIL"))
private void renderWorldFinish(float delta, long time, MatrixStack matrixStack, CallbackInfo ci) {
RenderQueue.get().setTrackRender(null);
@Inject(method = "renderCenter", at = @At("TAIL"))
private void renderCenterFinish(float delta, long time, CallbackInfo ci) {
RenderQueue.get().setTrackRender(false);
}
}
@@ -1,24 +0,0 @@
package kaptainwutax.seedcracker.mixin;
import kaptainwutax.seedcracker.init.KeyBindings;
import net.minecraft.client.options.KeyBinding;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Map;
@Mixin(KeyBinding.class)
public class KeyBindingMixin {
@Shadow @Final private static Map<String, Integer> categoryOrderMap;
static {
int start = categoryOrderMap.size();
for(String category: KeyBindings.CATEGORY_REGISTRY) {
categoryOrderMap.put(category, start++);
}
}
}
@@ -18,9 +18,4 @@ public class Cube extends Cuboid {
super(pos, new Vec3i(1, 1, 1), color);
}
@Override
public BlockPos getPos() {
return this.start;
}
}
@@ -1,7 +1,6 @@
package kaptainwutax.seedcracker.render;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
@@ -25,10 +24,6 @@ public class Cuboid extends Renderer {
this(start, new Vec3i(end.getX() - start.getX(), end.getY() - start.getY(), end.getZ() - start.getZ()), color);
}
public Cuboid(BlockBox box, Vector4f color) {
this(new BlockPos(box.minX, box.minY, box.minZ), new BlockPos(box.maxX, box.maxY, box.maxZ), color);
}
public Cuboid(BlockPos start, Vec3i size, Vector4f color) {
this.start = start;
this.size = size;
@@ -57,9 +52,4 @@ public class Cuboid extends Renderer {
}
}
@Override
public BlockPos getPos() {
return this.start.add(this.size.getX() / 2, this.size.getY() / 2, this.size.getZ() / 2);
}
}
@@ -5,7 +5,6 @@ import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class Line extends Renderer {
@@ -34,7 +33,7 @@ public class Line extends Renderer {
Vec3d camPos = this.mc.gameRenderer.getCamera().getPos();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
BufferBuilder buffer = tessellator.getBufferBuilder();
//This is how thick the line is.
GlStateManager.lineWidth(2.0f);
@@ -49,24 +48,18 @@ public class Line extends Renderer {
}
protected void putVertex(BufferBuilder buffer, Vec3d camPos, Vec3d pos) {
buffer.vertex(
pos.getX() - camPos.x,
pos.getY() - camPos.y,
pos.getZ() - camPos.z
).color(
this.color.getX(),
this.color.getY(),
this.color.getZ(),
this.color.getW()
).next();
}
@Override
public BlockPos getPos() {
double x = (this.end.getX() - this.start.getX()) / 2 + this.start.getX();
double y = (this.end.getY() - this.start.getY()) / 2 + this.start.getY();
double z = (this.end.getZ() - this.start.getZ()) / 2 + this.start.getZ();
return new BlockPos(x, y, z);
for(int i = 0; i < 2; i++) {
buffer.vertex(
pos.getX() - camPos.x,
pos.getY() - camPos.y,
pos.getZ() - camPos.z
).color(
this.color.getX(),
this.color.getY(),
this.color.getZ(),
this.color.getW()
).next();
}
}
}
@@ -1,22 +1,19 @@
package kaptainwutax.seedcracker.render;
import net.minecraft.client.util.math.MatrixStack;
import java.util.*;
import java.util.function.Consumer;
public class RenderQueue {
private final static RenderQueue INSTANCE = new RenderQueue();
private Map<String, List<Consumer<MatrixStack>>> typeRunnableMap = new HashMap<>();
private MatrixStack matrixStack = null;
private Map<String, List<Runnable>> typeRunnableMap = new HashMap<>();
private boolean trackRender = false;
public static RenderQueue get() {
return INSTANCE;
}
public void add(String type, Consumer<MatrixStack> runnable) {
public void add(String type, Runnable runnable) {
Objects.requireNonNull(type);
Objects.requireNonNull(runnable);
@@ -24,11 +21,11 @@ public class RenderQueue {
this.typeRunnableMap.put(type, new ArrayList<>());
}
List<Consumer<MatrixStack>> runnableList = this.typeRunnableMap.get(type);
List<Runnable> runnableList = this.typeRunnableMap.get(type);
runnableList.add(runnable);
}
public void remove(String type, Consumer<MatrixStack> runnable) {
public void remove(String type, Runnable runnable) {
Objects.requireNonNull(type);
Objects.requireNonNull(runnable);
@@ -36,17 +33,17 @@ public class RenderQueue {
return;
}
List<Consumer<MatrixStack>> runnableList = this.typeRunnableMap.get(type);
List<Runnable> runnableList = this.typeRunnableMap.get(type);
runnableList.remove(runnable);
}
public void setTrackRender(MatrixStack matrixStack) {
this.matrixStack = matrixStack;
public void setTrackRender(boolean flag) {
this.trackRender = flag;
}
public void onRender(String type) {
if(this.matrixStack == null || !this.typeRunnableMap.containsKey(type))return;
this.typeRunnableMap.get(type).forEach(r -> r.accept(this.matrixStack));
if(!this.trackRender || !this.typeRunnableMap.containsKey(type))return;
this.typeRunnableMap.get(type).forEach(Runnable::run);
}
}
@@ -10,8 +10,6 @@ public abstract class Renderer {
public abstract void render();
public abstract BlockPos getPos();
protected Vec3d toVec3d(BlockPos pos) {
return new Vec3d(pos.getX(), pos.getY(), pos.getZ());
}
@@ -1,17 +1,21 @@
package kaptainwutax.seedcracker.util;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.TextFormat;
import net.minecraft.client.util.TextComponentUtil;
import net.minecraft.text.Texts;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.LiteralText;
import static net.minecraft.util.Formatting.RED;
import static net.minecraft.util.Formatting.YELLOW;
public class Log {
public static void debug(String message) {
PlayerEntity player = getPlayer();
if(player != null) {
schedule(() -> player.addChatMessage(new LiteralText(message), false));
player.addChatMessage(new LiteralText(message), false);
}
}
@@ -19,7 +23,7 @@ public class Log {
PlayerEntity player = getPlayer();
if(player != null) {
schedule(() -> player.addChatMessage(new LiteralText(TextFormat.YELLOW + message), false));
player.addChatMessage(new LiteralText(YELLOW + message), false);
}
}
@@ -27,14 +31,10 @@ public class Log {
PlayerEntity player = getPlayer();
if(player != null) {
schedule(() -> player.addChatMessage(new LiteralText(TextFormat.RED + message), false));
player.addChatMessage(new LiteralText(RED + message), false);
}
}
private static void schedule(Runnable runnable) {
MinecraftClient.getInstance().execute(runnable);
}
private static PlayerEntity getPlayer() {
return MinecraftClient.getInstance().player;
}
@@ -11,11 +11,12 @@ public class PosIterator {
Set<BlockPos> result = new HashSet<>();
for(int x = start.getX(); x <= end.getX(); x++) {
for(int z = start.getZ(); z <= end.getZ(); z++) {
for(int y = start.getY(); y <= end.getY(); y++) {
result.add(new BlockPos(x, y, z));
for(int y = start.getY(); y <= end.getY(); y++) {
for(int z = start.getZ(); z <= end.getZ(); z++) {
result.add(new BlockPos(x, y, z));
}
}
}
}
return result;
@@ -2,8 +2,6 @@ package kaptainwutax.seedcracker.util;
import kaptainwutax.seedcracker.util.math.LCG;
import java.util.Random;
public class Rand implements Cloneable {
public static final LCG JAVA_LCG = new LCG(0x5DEECE66DL, 0xBL, 1L << 48);
@@ -71,10 +69,6 @@ public class Rand implements Cloneable {
return (((long)this.next(27) << 27) + this.next(27)) / (double)(1L << 54);
}
public Random toRandom() {
return new Random(this.seed ^ JAVA_LCG.multiplier);
}
@Override
public boolean equals(Object obj) {
if(obj == this)return true;
@@ -1,50 +0,0 @@
package kaptainwutax.seedcracker.util;
public class Seeds {
public static long setRegionSeed(Rand rand, long worldSeed, int regionX, int regionZ, int salt) {
long seed = (long)regionX * 341873128712L + (long)regionZ * 132897987541L + worldSeed + (long)salt;
if(rand != null)rand.setSeed(seed, true);
return seed;
}
public static long setPopulationSeed(Rand rand, long worldSeed, int posX, int posZ) {
if(rand == null)rand = new Rand(0L);
rand.setSeed(worldSeed, true);
long a = rand.nextLong() | 1L;
long b = rand.nextLong() | 1L;
long seed = (long)posX * a + (long)posZ * b ^ worldSeed;
rand.setSeed(seed, true);
return seed;
}
public static long setStructureStartSeed(Rand rand, long worldSeed, int chunkX, int chunkZ) {
if(rand == null)rand = new Rand(0L);
rand.setSeed(worldSeed, true);
long a = rand.nextLong();
long b = rand.nextLong();
long seed = (long)chunkX * a ^ (long)chunkZ * b ^ worldSeed;
rand.setSeed(seed, true);
return seed;
}
public static long setWeakSeed(Rand rand, long worldSeed, int chunkX, int chunkZ) {
int sX = chunkX >> 4;
int sZ = chunkZ >> 4;
long seed = (long)(sX ^ sZ << 4) ^ worldSeed;
if(rand != null) {
rand.setSeed(seed, true);
rand.nextInt();
}
return seed;
}
public static long setSlimeChunkSeed(Rand rand, long worldSeed, int chunkX, int chunkZ, long salt) {
long seed = worldSeed + (long)(chunkX * chunkX * 4987142) + (long)(chunkX * 5947611) + (long)(chunkZ * chunkZ) * 4392871L + (long)(chunkZ * 389711) ^ salt;
if(rand != null)rand.setSeed(seed, true);
return seed;
}
}
@@ -1,53 +0,0 @@
package kaptainwutax.seedcracker.util.loot;
import net.minecraft.client.MinecraftClient;
import net.minecraft.loot.context.LootContext;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.WorldGenerationProgressListener;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.WorldSaveHandler;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.level.LevelInfo;
import net.minecraft.world.level.LevelProperties;
import java.io.File;
public class LootBuilder extends LootContext.Builder {
private static final FakeWorld FAKE_WORLD = new FakeWorld();
public LootBuilder() {
super(FAKE_WORLD);
}
private static class FakeWorld extends ServerWorld {
public FakeWorld() {
super(new IntegratedServer(
MinecraftClient.getInstance(), null, null,
new LevelInfo(new LevelProperties(new CompoundTag(), null, 0, null)),
null, null, null, null, null
), Runnable::run, new WorldSaveHandler(new File("foo"), "bar", null, null),
new LevelProperties(new CompoundTag(), null, 0, null),
DimensionType.OVERWORLD, null, new WorldGenerationProgressListener() {
@Override
public void start(ChunkPos var1) {
}
@Override
public void setChunkStatus(ChunkPos var1, ChunkStatus var2) {
}
@Override
public void stop() {
}
});
}
}
}
@@ -1,55 +0,0 @@
package kaptainwutax.seedcracker.util.loot;
import net.minecraft.block.Blocks;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.Items;
import net.minecraft.item.map.MapIcon;
import net.minecraft.loot.ConstantLootTableRange;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.UniformLootTableRange;
import net.minecraft.loot.entry.EmptyEntry;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.function.*;
public class MCLootTables {
public static LootTable ABANDONED_MINESHAFT_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.GOLDEN_APPLE).setWeight(20)).withEntry(ItemEntry.builder(Items.ENCHANTED_GOLDEN_APPLE)).withEntry(ItemEntry.builder(Items.NAME_TAG).setWeight(30)).withEntry(ItemEntry.builder(Items.BOOK).setWeight(10).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.IRON_PICKAXE).setWeight(5)).withEntry(EmptyEntry.Serializer().setWeight(5))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 4.0F)).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.REDSTONE).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 9.0F)))).withEntry(ItemEntry.builder(Items.LAPIS_LAZULI).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 9.0F)))).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.MELON_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.PUMPKIN_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BEETROOT_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F))))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(3)).withEntry(ItemEntry.builder(Blocks.RAIL).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 8.0F)))).withEntry(ItemEntry.builder(Blocks.POWERED_RAIL).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Blocks.DETECTOR_RAIL).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Blocks.ACTIVATOR_RAIL).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Blocks.TORCH).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 16.0F))))).create();
public static LootTable BURIED_TREASURE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.HEART_OF_THE_SEA))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(5.0F, 8.0F)).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Blocks.TNT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F))))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 3.0F)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F)))).withEntry(ItemEntry.builder(Items.PRISMARINE_CRYSTALS).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F))))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(0.0F, 1.0F)).withEntry(ItemEntry.builder(Items.LEATHER_CHESTPLATE)).withEntry(ItemEntry.builder(Items.IRON_SWORD))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(2)).withEntry(ItemEntry.builder(Items.COOKED_COD).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.COOKED_SALMON).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F))))).create();
public static LootTable DESERT_PYRAMID_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 4.0F)).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BONE).setWeight(25).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 6.0F)))).withEntry(ItemEntry.builder(Items.SPIDER_EYE).setWeight(25).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(25).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(20)).withEntry(ItemEntry.builder(Items.IRON_HORSE_ARMOR).setWeight(15)).withEntry(ItemEntry.builder(Items.GOLDEN_HORSE_ARMOR).setWeight(10)).withEntry(ItemEntry.builder(Items.DIAMOND_HORSE_ARMOR).setWeight(5)).withEntry(ItemEntry.builder(Items.BOOK).setWeight(20).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.GOLDEN_APPLE).setWeight(20)).withEntry(ItemEntry.builder(Items.ENCHANTED_GOLDEN_APPLE).setWeight(2)).withEntry(EmptyEntry.Serializer().setWeight(15))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(4)).withEntry(ItemEntry.builder(Items.BONE).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.GUNPOWDER).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.STRING).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Blocks.SAND).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F))))).create();
public static LootTable END_CITY_TREASURE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 6.0F)).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 6.0F)))).withEntry(ItemEntry.builder(Items.BEETROOT_SEEDS).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 10.0F)))).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(3)).withEntry(ItemEntry.builder(Items.IRON_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.GOLDEN_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.DIAMOND_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.DIAMOND_SWORD).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.DIAMOND_BOOTS).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.DIAMOND_CHESTPLATE).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.DIAMOND_LEGGINGS).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.DIAMOND_HELMET).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.DIAMOND_PICKAXE).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.DIAMOND_SHOVEL).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.IRON_SWORD).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.IRON_BOOTS).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.IRON_CHESTPLATE).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.IRON_LEGGINGS).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.IRON_HELMET).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.IRON_PICKAXE).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments())).withEntry(ItemEntry.builder(Items.IRON_SHOVEL).setWeight(3).withFunction(EnchantWithLevelsLootFunction.builder(UniformLootTableRange.between(20.0F, 39.0F)).allowTreasureEnchantments()))).create();
public static LootTable IGLOO_CHEST_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 8.0F)).withEntry(ItemEntry.builder(Items.APPLE).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.GOLD_NUGGET).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.STONE_AXE).setWeight(2)).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(10)).withEntry(ItemEntry.builder(Items.EMERALD)).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 3.0F))))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.GOLDEN_APPLE))).create();
public static LootTable JUNGLE_TEMPLE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 6.0F)).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 7.0F)))).withEntry(ItemEntry.builder(Blocks.BAMBOO).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BONE).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 6.0F)))).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(16).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(3)).withEntry(ItemEntry.builder(Items.IRON_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.GOLDEN_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.DIAMOND_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.BOOK).withFunction(EnchantWithLevelsLootFunction.builder(ConstantLootTableRange.create(30)).allowTreasureEnchantments()))).create();
public static LootTable JUNGLE_TEMPLE_DISPENSER_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 2.0F)).withEntry(ItemEntry.builder(Items.ARROW).setWeight(30).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 7.0F))))).create();
public static LootTable NETHER_BRIDGE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 4.0F)).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.GOLDEN_SWORD).setWeight(5)).withEntry(ItemEntry.builder(Items.GOLDEN_CHESTPLATE).setWeight(5)).withEntry(ItemEntry.builder(Items.FLINT_AND_STEEL).setWeight(5)).withEntry(ItemEntry.builder(Items.NETHER_WART).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(10)).withEntry(ItemEntry.builder(Items.GOLDEN_HORSE_ARMOR).setWeight(8)).withEntry(ItemEntry.builder(Items.IRON_HORSE_ARMOR).setWeight(5)).withEntry(ItemEntry.builder(Items.DIAMOND_HORSE_ARMOR).setWeight(3)).withEntry(ItemEntry.builder(Blocks.OBSIDIAN).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F))))).create();
public static LootTable PILLAGER_OUTPOST_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(0.0F, 1.0F)).withEntry(ItemEntry.builder(Items.CROSSBOW))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 3.0F)).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(7).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.POTATO).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.CARROT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 5.0F))))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 3.0F)).withEntry(ItemEntry.builder(Blocks.DARK_OAK_LOG).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 3.0F))))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 3.0F)).withEntry(ItemEntry.builder(Items.EXPERIENCE_BOTTLE).setWeight(7)).withEntry(ItemEntry.builder(Items.STRING).setWeight(4).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 6.0F)))).withEntry(ItemEntry.builder(Items.ARROW).setWeight(4).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.TRIPWIRE_HOOK).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BOOK).setWeight(1).withFunction(EnchantRandomlyLootFunction.builder()))).create();
public static LootTable SHIPWRECK_MAP_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.MAP).withFunction(ExplorationMapLootFunction.create().withDestination("buried_treasure").withDecoration(MapIcon.Type.RED_X).withZoom((byte)1).withSkipExistingChunks(false)))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(3)).withEntry(ItemEntry.builder(Items.COMPASS)).withEntry(ItemEntry.builder(Items.MAP)).withEntry(ItemEntry.builder(Items.CLOCK)).withEntry(ItemEntry.builder(Items.PAPER).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 10.0F)))).withEntry(ItemEntry.builder(Items.FEATHER).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.BOOK).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F))))).create();
public static LootTable SHIPWRECK_SUPPLY_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 10.0F)).withEntry(ItemEntry.builder(Items.PAPER).setWeight(8).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 12.0F)))).withEntry(ItemEntry.builder(Items.POTATO).setWeight(7).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 6.0F)))).withEntry(ItemEntry.builder(Items.POISONOUS_POTATO).setWeight(7).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 6.0F)))).withEntry(ItemEntry.builder(Items.CARROT).setWeight(7).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(7).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(8.0F, 21.0F)))).withEntry(ItemEntry.builder(Items.SUSPICIOUS_STEW).setWeight(10).withFunction(SetStewEffectLootFunction.builder().withEffect(StatusEffects.NIGHT_VISION, UniformLootTableRange.between(7.0F, 10.0F)).withEffect(StatusEffects.JUMP_BOOST, UniformLootTableRange.between(7.0F, 10.0F)).withEffect(StatusEffects.WEAKNESS, UniformLootTableRange.between(6.0F, 8.0F)).withEffect(StatusEffects.BLINDNESS, UniformLootTableRange.between(5.0F, 7.0F)).withEffect(StatusEffects.POISON, UniformLootTableRange.between(10.0F, 20.0F)).withEffect(StatusEffects.SATURATION, UniformLootTableRange.between(7.0F, 10.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(5.0F, 24.0F)))).withEntry(ItemEntry.builder(Blocks.PUMPKIN).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.BAMBOO).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.GUNPOWDER).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Blocks.TNT).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F)))).withEntry(ItemEntry.builder(Items.LEATHER_HELMET).setWeight(3).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.LEATHER_CHESTPLATE).setWeight(3).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.LEATHER_LEGGINGS).setWeight(3).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.LEATHER_BOOTS).setWeight(3).withFunction(EnchantRandomlyLootFunction.builder()))).create();
public static LootTable SHIPWRECK_TREASURE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 6.0F)).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(90).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(40).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(5)).withEntry(ItemEntry.builder(Items.EXPERIENCE_BOTTLE).setWeight(5))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 5.0F)).withEntry(ItemEntry.builder(Items.IRON_NUGGET).setWeight(50).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 10.0F)))).withEntry(ItemEntry.builder(Items.GOLD_NUGGET).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 10.0F)))).withEntry(ItemEntry.builder(Items.LAPIS_LAZULI).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 10.0F))))).create();
public static LootTable SIMPLE_DUNGEON_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 3.0F)).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(20)).withEntry(ItemEntry.builder(Items.GOLDEN_APPLE).setWeight(15)).withEntry(ItemEntry.builder(Items.ENCHANTED_GOLDEN_APPLE).setWeight(2)).withEntry(ItemEntry.builder(Items.MUSIC_DISC_13).setWeight(15)).withEntry(ItemEntry.builder(Items.MUSIC_DISC_CAT).setWeight(15)).withEntry(ItemEntry.builder(Items.NAME_TAG).setWeight(20)).withEntry(ItemEntry.builder(Items.GOLDEN_HORSE_ARMOR).setWeight(10)).withEntry(ItemEntry.builder(Items.IRON_HORSE_ARMOR).setWeight(15)).withEntry(ItemEntry.builder(Items.DIAMOND_HORSE_ARMOR).setWeight(5)).withEntry(ItemEntry.builder(Items.BOOK).setWeight(10).withFunction(EnchantRandomlyLootFunction.builder()))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 4.0F)).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(20)).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BUCKET).setWeight(10)).withEntry(ItemEntry.builder(Items.REDSTONE).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.MELON_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.PUMPKIN_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BEETROOT_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F))))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(3)).withEntry(ItemEntry.builder(Items.BONE).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.GUNPOWDER).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.STRING).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F))))).create();
public static LootTable SPAWN_BONUS_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.STONE_AXE)).withEntry(ItemEntry.builder(Items.WOODEN_AXE).setWeight(3))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.STONE_PICKAXE)).withEntry(ItemEntry.builder(Items.WOODEN_PICKAXE).setWeight(3))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(3)).withEntry(ItemEntry.builder(Items.APPLE).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F)))).withEntry(ItemEntry.builder(Items.SALMON).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F))))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(4)).withEntry(ItemEntry.builder(Items.STICK).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 12.0F)))).withEntry(ItemEntry.builder(Blocks.OAK_PLANKS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 12.0F)))).withEntry(ItemEntry.builder(Blocks.OAK_LOG).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.SPRUCE_LOG).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.BIRCH_LOG).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.JUNGLE_LOG).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.ACACIA_LOG).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.DARK_OAK_LOG).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F))))).create();
public static LootTable STRONGHOLD_CORRIDOR_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 3.0F)).withEntry(ItemEntry.builder(Items.ENDER_PEARL).setWeight(10)).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.REDSTONE).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 9.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.APPLE).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_PICKAXE).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_SWORD).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_CHESTPLATE).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_HELMET).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_LEGGINGS).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_BOOTS).setWeight(5)).withEntry(ItemEntry.builder(Items.GOLDEN_APPLE)).withEntry(ItemEntry.builder(Items.SADDLE)).withEntry(ItemEntry.builder(Items.IRON_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.GOLDEN_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.DIAMOND_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.BOOK).withFunction(EnchantWithLevelsLootFunction.builder(ConstantLootTableRange.create(30)).allowTreasureEnchantments()))).create();
public static LootTable STRONGHOLD_CROSSING_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 4.0F)).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.REDSTONE).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(4.0F, 9.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.APPLE).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_PICKAXE)).withEntry(ItemEntry.builder(Items.BOOK).withFunction(EnchantWithLevelsLootFunction.builder(ConstantLootTableRange.create(30)).allowTreasureEnchantments()))).create();
public static LootTable STRONGHOLD_LIBRARY_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 10.0F)).withEntry(ItemEntry.builder(Items.BOOK).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.PAPER).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.MAP)).withEntry(ItemEntry.builder(Items.COMPASS)).withEntry(ItemEntry.builder(Items.BOOK).setWeight(10).withFunction(EnchantWithLevelsLootFunction.builder(ConstantLootTableRange.create(30)).allowTreasureEnchantments()))).create();
public static LootTable UNDERWATER_RUIN_BIG_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 8.0F)).withEntry(ItemEntry.builder(Items.COAL).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.GOLD_NUGGET).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.EMERALD)).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 3.0F))))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.GOLDEN_APPLE)).withEntry(ItemEntry.builder(Items.BOOK).setWeight(5).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.LEATHER_CHESTPLATE)).withEntry(ItemEntry.builder(Items.GOLDEN_HELMET)).withEntry(ItemEntry.builder(Items.FISHING_ROD).setWeight(5).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.MAP).setWeight(10).withFunction(ExplorationMapLootFunction.create().withDestination("buried_treasure").withDecoration(MapIcon.Type.RED_X).withZoom((byte)1).withSkipExistingChunks(false)))).create();
public static LootTable UNDERWATER_RUIN_SMALL_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(2.0F, 8.0F)).withEntry(ItemEntry.builder(Items.COAL).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.STONE_AXE).setWeight(2)).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(5)).withEntry(ItemEntry.builder(Items.EMERALD)).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 3.0F))))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(1)).withEntry(ItemEntry.builder(Items.LEATHER_CHESTPLATE)).withEntry(ItemEntry.builder(Items.GOLDEN_HELMET)).withEntry(ItemEntry.builder(Items.FISHING_ROD).setWeight(5).withFunction(EnchantRandomlyLootFunction.builder())).withEntry(ItemEntry.builder(Items.MAP).setWeight(5).withFunction(ExplorationMapLootFunction.create().withDestination("buried_treasure").withDecoration(MapIcon.Type.RED_X).withZoom((byte)1).withSkipExistingChunks(false)))).create();
public static LootTable VILLAGE_WEAPONSMITH_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.APPLE).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_PICKAXE).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_SWORD).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_CHESTPLATE).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_HELMET).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_LEGGINGS).setWeight(5)).withEntry(ItemEntry.builder(Items.IRON_BOOTS).setWeight(5)).withEntry(ItemEntry.builder(Blocks.OBSIDIAN).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 7.0F)))).withEntry(ItemEntry.builder(Blocks.OAK_SAPLING).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(3.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(3)).withEntry(ItemEntry.builder(Items.IRON_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.GOLDEN_HORSE_ARMOR)).withEntry(ItemEntry.builder(Items.DIAMOND_HORSE_ARMOR))).create();
public static LootTable VILLAGE_TOOLSMITH_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Items.DIAMOND).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_PICKAXE).setWeight(5)).withEntry(ItemEntry.builder(Items.COAL).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.STICK).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.IRON_SHOVEL).setWeight(5))).create();
public static LootTable VILLAGE_CARTOGRAPHER_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Items.MAP).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.PAPER).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.COMPASS).setWeight(5)).withEntry(ItemEntry.builder(Items.BREAD).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.STICK).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F))))).create();
public static LootTable VILLAGE_MASON_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Items.CLAY_BALL).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.FLOWER_POT).setWeight(1)).withEntry(ItemEntry.builder(Blocks.STONE).setWeight(2)).withEntry(ItemEntry.builder(Blocks.STONE_BRICKS).setWeight(2)).withEntry(ItemEntry.builder(Items.BREAD).setWeight(4).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.YELLOW_DYE).setWeight(1)).withEntry(ItemEntry.builder(Blocks.SMOOTH_STONE).setWeight(1)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1))).create();
public static LootTable VILLAGE_ARMORER_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(4).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.IRON_HELMET).setWeight(1)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1))).create();
public static LootTable VILLAGE_SHEPARD_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Blocks.WHITE_WOOL).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Blocks.BLACK_WOOL).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.GRAY_WOOL).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.BROWN_WOOL).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Blocks.LIGHT_GRAY_WOOL).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1)).withEntry(ItemEntry.builder(Items.SHEARS).setWeight(1)).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 6.0F))))).create();
public static LootTable VILLAGE_BUTCHER_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1)).withEntry(ItemEntry.builder(Items.PORKCHOP).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BEEF).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.MUTTON).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F))))).create();
public static LootTable VILLAGE_FLETCHER_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1)).withEntry(ItemEntry.builder(Items.ARROW).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.FEATHER).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.EGG).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.FLINT).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.STICK).setWeight(6).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F))))).create();
public static LootTable VILLAGE_FISHER_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1)).withEntry(ItemEntry.builder(Items.COD).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.SALMON).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.WATER_BUCKET).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.BARREL).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.WHEAT_SEEDS).setWeight(3).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F))))).create();
public static LootTable VILLAGE_TANNERY_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 5.0F)).withEntry(ItemEntry.builder(Items.LEATHER).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.LEATHER_CHESTPLATE).setWeight(2)).withEntry(ItemEntry.builder(Items.LEATHER_BOOTS).setWeight(2)).withEntry(ItemEntry.builder(Items.LEATHER_HELMET).setWeight(2)).withEntry(ItemEntry.builder(Items.BREAD).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.LEATHER_LEGGINGS).setWeight(2)).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(1)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F))))).create();
public static LootTable VILLAGE_TEMPLE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Items.REDSTONE).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(7).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(7).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.LAPIS_LAZULI).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F))))).create();
public static LootTable VILLAGE_PLAINS_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Items.GOLD_NUGGET).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.DANDELION).setWeight(2)).withEntry(ItemEntry.builder(Items.POPPY).setWeight(1)).withEntry(ItemEntry.builder(Items.POTATO).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.APPLE).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.BOOK).setWeight(1)).withEntry(ItemEntry.builder(Items.FEATHER).setWeight(1)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Blocks.OAK_SAPLING).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F))))).create();
public static LootTable VILLAGE_TAIGA_HOUSE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Items.IRON_NUGGET).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.FERN).setWeight(2)).withEntry(ItemEntry.builder(Items.LARGE_FERN).setWeight(2)).withEntry(ItemEntry.builder(Items.POTATO).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.SWEET_BERRIES).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.PUMPKIN_SEEDS).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.PUMPKIN_PIE).setWeight(1)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Blocks.SPRUCE_SAPLING).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.SPRUCE_SIGN).setWeight(1)).withEntry(ItemEntry.builder(Items.SPRUCE_LOG).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F))))).create();
public static LootTable VILLAGE_SAVANNA_HOUSE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Items.GOLD_NUGGET).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.GRASS).setWeight(5)).withEntry(ItemEntry.builder(Items.TALL_GRASS).setWeight(5)).withEntry(ItemEntry.builder(Items.BREAD).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.WHEAT_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Blocks.ACACIA_SAPLING).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F)))).withEntry(ItemEntry.builder(Items.SADDLE).setWeight(1)).withEntry(ItemEntry.builder(Blocks.TORCH).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 2.0F)))).withEntry(ItemEntry.builder(Items.BUCKET).setWeight(1))).create();
public static LootTable VILLAGE_SNOWY_HOUSE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Blocks.BLUE_ICE).setWeight(1)).withEntry(ItemEntry.builder(Blocks.SNOW_BLOCK).setWeight(4)).withEntry(ItemEntry.builder(Items.POTATO).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BEETROOT_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 5.0F)))).withEntry(ItemEntry.builder(Items.BEETROOT_SOUP).setWeight(1)).withEntry(ItemEntry.builder(Items.FURNACE).setWeight(1)).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.SNOWBALL).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F))))).create();
public static LootTable VILLAGE_DESERT_HOUSE_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(3.0F, 8.0F)).withEntry(ItemEntry.builder(Items.CLAY_BALL).setWeight(1)).withEntry(ItemEntry.builder(Items.GREEN_DYE).setWeight(1)).withEntry(ItemEntry.builder(Blocks.CACTUS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 7.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BOOK).setWeight(1)).withEntry(ItemEntry.builder(Blocks.DEAD_BUSH).setWeight(2).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F)))).withEntry(ItemEntry.builder(Items.EMERALD).setWeight(1).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 3.0F))))).create();
public static LootTable WOODLAND_MANSION_CHEST = LootTable.builder().withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 3.0F)).withEntry(ItemEntry.builder(Items.LEAD).setWeight(20)).withEntry(ItemEntry.builder(Items.GOLDEN_APPLE).setWeight(15)).withEntry(ItemEntry.builder(Items.ENCHANTED_GOLDEN_APPLE).setWeight(2)).withEntry(ItemEntry.builder(Items.MUSIC_DISC_13).setWeight(15)).withEntry(ItemEntry.builder(Items.MUSIC_DISC_CAT).setWeight(15)).withEntry(ItemEntry.builder(Items.NAME_TAG).setWeight(20)).withEntry(ItemEntry.builder(Items.CHAINMAIL_CHESTPLATE).setWeight(10)).withEntry(ItemEntry.builder(Items.DIAMOND_HOE).setWeight(15)).withEntry(ItemEntry.builder(Items.DIAMOND_CHESTPLATE).setWeight(5)).withEntry(ItemEntry.builder(Items.BOOK).setWeight(10).withFunction(EnchantRandomlyLootFunction.builder()))).withPool(LootPool.builder().withRolls(UniformLootTableRange.between(1.0F, 4.0F)).withEntry(ItemEntry.builder(Items.IRON_INGOT).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.GOLD_INGOT).setWeight(5).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BREAD).setWeight(20)).withEntry(ItemEntry.builder(Items.WHEAT).setWeight(20).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BUCKET).setWeight(10)).withEntry(ItemEntry.builder(Items.REDSTONE).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.COAL).setWeight(15).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.MELON_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.PUMPKIN_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F)))).withEntry(ItemEntry.builder(Items.BEETROOT_SEEDS).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(2.0F, 4.0F))))).withPool(LootPool.builder().withRolls(ConstantLootTableRange.create(3)).withEntry(ItemEntry.builder(Items.BONE).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.GUNPOWDER).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.ROTTEN_FLESH).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F)))).withEntry(ItemEntry.builder(Items.STRING).setWeight(10).withFunction(SetCountLootFunction.builder(UniformLootTableRange.between(1.0F, 8.0F))))).create();
}
@@ -1,14 +0,0 @@
package kaptainwutax.seedcracker.util.math;
import java.util.function.BiPredicate;
public class Predicates {
public static BiPredicate<Integer, Integer> EQUAL_TO = Integer::equals;
public static BiPredicate<Integer, Integer> NOT_EQUAL_TO = (a, b) -> !a.equals(b);
public static BiPredicate<Integer, Integer> LESS_THAN = (a, b) -> a < b;
public static BiPredicate<Integer, Integer> MORE_THAN = (a, b) -> a > b;
public static BiPredicate<Integer, Integer> LESS_OR_EQUAL_TO = (a, b) -> a <= b;
public static BiPredicate<Integer, Integer> MORE_OR_EQUAL_TO = (a, b) -> a >= b;
}
@@ -1,4 +0,0 @@
{
"key.categories.seedcracker": "Seed Cracker",
"key.open_menu": "Open Menu"
}
@@ -1,6 +0,0 @@
{
"parent": "item/handheld",
"textures": {
"layer0": "seedcracker:item/gui_item"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

+2 -8
View File
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"id": "seedcracker",
"version": "0.0.2",
"version": "0.0.1",
"name": "Seed Cracker",
"description": "This is an example description! Tell everyone what your mod is about!",
@@ -27,15 +27,9 @@
],
"depends": {
"fabricloader": ">=0.4.0",
"fabric": "*",
"minecraft": ">=1.15"
"fabricloader": ">=0.4.0"
},
"suggests": {
"flamingo": "*"
},
"custom": {
"modmenu:api": true,
"modmenu:clientsideOnly": true
}
}
+1 -3
View File
@@ -9,9 +9,7 @@
"GameRendererMixin",
"ClientPlayNetworkHandlerMixin",
"ClientWorldMixin",
"ClientPlayerEntityMixin",
"GameOptionsMixin",
"KeyBindingMixin"
"ClientPlayerEntityMixin"
],
"injectors": {
"defaultRequire": 1