Skip to content

Commit

Permalink
Adds custom loot tables for chests
Browse files Browse the repository at this point in the history
  • Loading branch information
tastybento committed Sep 2, 2019
1 parent 1aee7ef commit b5c3fae
Show file tree
Hide file tree
Showing 4 changed files with 630 additions and 176 deletions.
59 changes: 54 additions & 5 deletions src/main/java/world/bentobox/skygrid/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,22 @@ public class Settings implements WorldSettings {
private String adminCommand = "sgadmin sga";

/* Chests */
@ConfigComment("Chest fill setting. 1 = normal, 0 = nothing, 2 or more for more items")
@ConfigComment("Number of unique items per chest")
@ConfigEntry(path = "world.chest-fill.overworld")
private int chestFill = 1;
private int chestFill = 5;
@ConfigComment("Nether chest fill setting")
@ConfigEntry(path = "world.chest-fill.nether")
private int chestFillNether = 1;
private int chestFillNether = 5;
@ConfigComment("The End chest fill setting")
@ConfigEntry(path = "world.chest-fill.end")
private int chestFillEnd = 1;
private int chestFillEnd = 5;
@ConfigComment("Chest items will be taken randomly from this list. All items have an equal chance.")
@ConfigEntry(path = "world.chest-items.overworld")
private List<String> chestItemsOverworld;
@ConfigEntry(path = "world.chest-items.nether")
private List<String> chestItemsNether;
@ConfigEntry(path = "world.chest-items.end")
private List<String> chestItemsEnd;

/* Blocks */
@ConfigComment("World block types. If the material cannot be placed, bedrock will be used.")
Expand Down Expand Up @@ -84,7 +91,7 @@ public class Settings implements WorldSettings {
/* SkyGrid */
@ConfigComment("Overworld has biomes - this will affect some block types and tree types.")
@ConfigEntry(path = "world.create-biomes")
private boolean createBiomes = true;
private boolean createBiomes = false;

@ConfigComment("The probability of a frame being created in a chunk. Frames are always at y=0.")
@ConfigEntry(path = "world.end-frame-probability")
Expand Down Expand Up @@ -1100,6 +1107,48 @@ public void setChestFillEnd(int chestFillEnd) {
this.chestFillEnd = chestFillEnd;
}

/**
* @return the chestItemsOverworld
*/
public List<String> getChestItemsOverworld() {
return chestItemsOverworld;
}

/**
* @param chestItemsOverworld the chestItemsOverworld to set
*/
public void setChestItemsOverworld(List<String> chestItemsOverworld) {
this.chestItemsOverworld = chestItemsOverworld;
}

/**
* @return the chestItemsNether
*/
public List<String> getChestItemsNether() {
return chestItemsNether;
}

/**
* @param chestItemsNether the chestItemsNether to set
*/
public void setChestItemsNether(List<String> chestItemsNether) {
this.chestItemsNether = chestItemsNether;
}

/**
* @return the chestItemsEnd
*/
public List<String> getChestItemsEnd() {
return chestItemsEnd;
}

/**
* @param chestItemsEnd the chestItemsEnd to set
*/
public void setChestItemsEnd(List<String> chestItemsEnd) {
this.chestItemsEnd = chestItemsEnd;
}

/**
* @return the deathsResetOnNewIsland
*/
Expand Down
51 changes: 26 additions & 25 deletions src/main/java/world/bentobox/skygrid/generators/RandomSeries.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,30 @@
*
*/
public class RandomSeries {
private final int[] reset;
private int[] series;
private int pos;

public RandomSeries(int size) {
reset = new int[size];
for (int i = 0; i < size; i++) {
reset[i] = i;
}
reset();
}

public void reset() {
pos = 0;
series = reset.clone();
}

public int next(Random random) {
int slot = pos + random.nextInt(series.length - pos);
int temp = series[pos];
series[pos] = series[slot];
series[slot] = temp;
return series[pos++];
}

private Random random = new Random();
private final int[] reset;
private int[] series;
private int pos;

public RandomSeries(int size) {
reset = new int[size];
for (int i = 0; i < size; i++) {
reset[i] = i;
}
reset();
}

public void reset() {
pos = 0;
series = reset.clone();
}

public int next() {
int slot = pos + random.nextInt(series.length - pos);
int temp = series[pos];
series[pos] = series[slot];
series[slot] = temp;
return series[pos++];
}

}
163 changes: 23 additions & 140 deletions src/main/java/world/bentobox/skygrid/generators/SkyGridPop.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package world.bentobox.skygrid.generators;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.TreeMap;
import java.util.stream.Collectors;
Expand All @@ -19,7 +17,6 @@
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.data.type.EndPortalFrame;
import org.bukkit.block.data.type.Sapling;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.inventory.Inventory;
Expand All @@ -32,11 +29,9 @@ public class SkyGridPop extends BlockPopulator {
private static final RandomSeries slt = new RandomSeries(27);
private final int size;
private SkyGrid addon;
private final static HashMap<Material, Double> END_ITEMS;
private final static List<Material> FOOD = Arrays.stream(Material.values()).filter(Material::isEdible).filter(m -> !m.equals(Material.POISONOUS_POTATO)).collect(Collectors.toList());
private final static List<Material> SPAWNEGGS = Arrays.stream(Material.values()).filter(m -> m.name().endsWith("SPAWN_EGG")).collect(Collectors.toList());
private final static List<Material> BLOCKS = Arrays.stream(Material.values()).filter(Material::isBlock).collect(Collectors.toList());
private final static List<Material> ITEMS = Arrays.stream(Material.values()).filter(Material::isItem).collect(Collectors.toList());
private final List<Material> chestItemsWorld;
private final List<Material> chestItemsNether;
private final List<Material> chestItemsEnd;

private final static Material[] SAPLING_TYPE = {
Material.ACACIA_SAPLING,
Expand All @@ -47,20 +42,17 @@ public class SkyGridPop extends BlockPopulator {
Material.SPRUCE_SAPLING
};

static {
// Hard code these probabilities. TODO: make these config.yml settings.
END_ITEMS = new HashMap<>();
// double format - integer part is the quantity, decimal is the probability
END_ITEMS.put(Material.FIREWORK_ROCKET, 20.2); // for elytra
END_ITEMS.put(Material.EMERALD, 1.1);
END_ITEMS.put(Material.CHORUS_FRUIT, 3.1);
END_ITEMS.put(Material.ELYTRA, 1.2);
END_ITEMS.put(Material.SHULKER_BOX, 1.1);
}

public SkyGridPop(SkyGrid addon) {
this.addon = addon;
this.size = addon.getSettings().getIslandHeight();
// Load the chest items
chestItemsWorld = addon.getSettings().getChestItemsOverworld().stream().map(Material::matchMaterial).filter(Objects::nonNull).collect(Collectors.toList());
chestItemsNether = addon.getSettings().getChestItemsNether().stream().map(Material::matchMaterial).filter(Objects::nonNull).collect(Collectors.toList());
chestItemsEnd = addon.getSettings().getChestItemsEnd().stream().map(Material::matchMaterial).filter(Objects::nonNull).collect(Collectors.toList());
addon.log("Loaded " + chestItemsWorld.size() + " chest items for world");
addon.log("Loaded " + chestItemsNether.size() + " chest items for nether world");
addon.log("Loaded " + chestItemsEnd.size() + " chest items for end world");

}

@Override
Expand Down Expand Up @@ -179,136 +171,27 @@ private void setSpawner(Block b, Random random, World world) {
private void setChest(Block b, Random random, World world) {
Chest chest = (Chest) b.getState();
Inventory inv = chest.getBlockInventory();
HashSet<ItemStack> set = new HashSet<>();
slt.reset();
switch (b.getWorld().getEnvironment()) {
case NETHER:
for (int i = 0; i < addon.getSettings().getChestFillNether(); i ++) {
if (random.nextDouble() < 0.7)
set.add(itemInRange(256, 294, random)); //weapon/random
if (random.nextDouble() < 0.7) {
ItemStack armor = itemInRange(298, 317, random); //armor
if (armor.getType().toString().endsWith("BOOTS")) {
if (random.nextDouble() < 0.5) {
armor.addEnchantment(Enchantment.PROTECTION_FALL, random.nextInt(4) + 1);
}
}
set.add(armor); //armor
}

if (random.nextDouble() < 0.9) {
// ghast, pigman, enderman
set.add(pickEgg(random, EntityType.GHAST, EntityType.PIG_ZOMBIE, EntityType.ENDERMAN)); //spawn eggs
} else if (random.nextDouble() < 0.9) {
// Blaze, Magma Cube
set.add(pickEgg(random, EntityType.BLAZE, EntityType.MAGMA_CUBE)); //spawn eggs
}
if (random.nextDouble() < 0.3) {

double rand1 = random.nextDouble();
if (rand1 < 0.1)
set.add(new ItemStack(Material.CLOCK)); // clock
else if (rand1 < 0.5) {
set.add(new ItemStack(Material.BLAZE_ROD));
} else if (rand1 < 0.6) {
set.add(new ItemStack(Material.SADDLE));
} else if (rand1 < 0.7) {
set.add(new ItemStack(Material.IRON_HORSE_ARMOR));
} else if (rand1 < 0.8) {
set.add(new ItemStack(Material.GOLDEN_HORSE_ARMOR));
} else if (rand1 < 0.9) {
set.add(new ItemStack(Material.DIAMOND_HORSE_ARMOR));
} else {
set.add(new ItemStack(Material.GHAST_TEAR));
}
}
}
break;
case NORMAL:
for (int i = 0; i < addon.getSettings().getChestFill(); i ++) {
set.add(new ItemStack(FOOD.get(random.nextInt(FOOD.size())), random.nextInt(3))); //food/tools
if (random.nextDouble() < 0.7) {
set.add(new ItemStack(FOOD.get(random.nextInt(FOOD.size())), random.nextInt(3))); //food/tools
set.add(new ItemStack(FOOD.get(random.nextInt(FOOD.size())), random.nextInt(3))); //food/tools
set.add(new ItemStack(FOOD.get(random.nextInt(FOOD.size())), random.nextInt(3))); //food/tools
}
if (random.nextDouble() < 0.2) {
set.add(new ItemStack(FOOD.get(random.nextInt(FOOD.size())), random.nextInt(3))); //food/tools
set.add(new ItemStack(FOOD.get(random.nextInt(FOOD.size())), random.nextInt(3))); //food/tools
}
if (random.nextDouble() < 0.1) {
set.add(new ItemStack(SPAWNEGGS.get(random.nextInt(SPAWNEGGS.size()))));
}
set.add(new ItemStack(BLOCKS.get(random.nextInt(BLOCKS.size())), random.nextInt(3)));
if (random.nextDouble() < 0.7) {
set.add(new ItemStack(BLOCKS.get(random.nextInt(BLOCKS.size())), random.nextInt(3)));
}
if (random.nextDouble() < 0.7) {
set.add(new ItemStack(BLOCKS.get(random.nextInt(BLOCKS.size())), random.nextInt(3)));
}
if (random.nextDouble() < 0.7) {
set.add(new ItemStack(BLOCKS.get(random.nextInt(BLOCKS.size())), random.nextInt(3)));
}
if (random.nextDouble() < 0.5) {
set.add(new ItemStack(ITEMS.get(random.nextInt(ITEMS.size())), random.nextInt(3)));
}
if (random.nextDouble() < 0.4) {
set.add(new ItemStack(ITEMS.get(random.nextInt(ITEMS.size())), random.nextInt(3)));
}
if (random.nextDouble() < 0.3) {
set.add(new ItemStack(ITEMS.get(random.nextInt(ITEMS.size())), random.nextInt(3)));
}
if (random.nextDouble() < 0.1) {
set.add(new ItemStack(Material.WATER_BUCKET));
}
for (int i = 0; i < addon.getSettings().getChestFillNether() && i < 27; i ++) {
ItemStack item = new ItemStack(this.chestItemsNether.get(random.nextInt(chestItemsNether.size())));
inv.setItem(slt.next(), item);
}
break;
case THE_END:
for (int i = 0; i < addon.getSettings().getChestFillEnd(); i ++) {
set.add(itemInRange(318, 350, random)); //food/tools
set.add(itemInRange(318, 350, random)); //food/tools
set.add(itemInRange(318, 350, random)); //food/tools
if (random.nextDouble() < 0.2)
set.add(new ItemStack(Material.ENDERMAN_SPAWN_EGG)); //enderman spawn egg
if (random.nextDouble() < 0.4)
set.add(itemInRange(256, 294, random)); //weapon/random
END_ITEMS.entrySet().forEach(en -> {
if (random.nextDouble() < en.getValue()) {
// The quantity and probability are encoded. The integer is the qty, the decimal the prob
int qty = en.getValue().intValue();
double probability = en.getValue() - qty;
if (random.nextDouble() < probability) {
set.add(new ItemStack(en.getKey(), qty));
}
}
});
for (Material mat : Material.values()) {
if (END_ITEMS.containsKey(mat)) {

}
}
if (random.nextDouble() < 0.2)
set.add(new ItemStack(Material.SHULKER_SPAWN_EGG)); //shulker spawn egg
for (int i = 0; i < addon.getSettings().getChestFillEnd() && i < 27; i ++) {
ItemStack item = new ItemStack(this.chestItemsEnd.get(random.nextInt(chestItemsEnd.size())));
inv.setItem(slt.next(), item);
}
break;
default:
for (int i = 0; i < addon.getSettings().getChestFill() && i < 27; i ++) {
ItemStack item = new ItemStack(this.chestItemsWorld.get(random.nextInt(chestItemsWorld.size())));
inv.setItem(slt.next(), item);
}
break;

}
// Put the first 27 items into the chest
set.stream().limit(27).forEach(i -> inv.setItem(slt.next(random), i));
slt.reset();
}

private ItemStack pickEgg(Random random, EntityType... type) {
EntityType choice = type[random.nextInt(type.length)];
if (choice == EntityType.PIG_ZOMBIE) {
return new ItemStack(Material.ZOMBIE_PIGMAN_SPAWN_EGG);
} else {
return new ItemStack(Material.valueOf(choice.name() + "_SPAWN_EGG"));
}
}
private ItemStack itemInRange(int min, int max, Random random) {
return new ItemStack(Arrays.asList(Material.values()).get(random.nextInt(max - min + 1) + min), 1);
}

}

0 comments on commit b5c3fae

Please sign in to comment.