Merge pull request #74 from SenseiKiwi/master
Improved Dungeon Loot and Selection
This commit is contained in:
commit
928b7d4cba
4 changed files with 92 additions and 31 deletions
|
@ -4,7 +4,10 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import net.minecraft.inventory.IInventory;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.WeightedRandom;
|
||||||
import net.minecraft.util.WeightedRandomChestContent;
|
import net.minecraft.util.WeightedRandomChestContent;
|
||||||
import net.minecraftforge.common.ChestGenHooks;
|
import net.minecraftforge.common.ChestGenHooks;
|
||||||
|
|
||||||
|
@ -33,6 +36,8 @@ public class DDLoot {
|
||||||
private static final int RARE_LOOT_WEIGHT = 1; //Same weight as music discs, golden apple
|
private static final int RARE_LOOT_WEIGHT = 1; //Same weight as music discs, golden apple
|
||||||
private static final int DUNGEON_CHEST_WEIGHT_INFLATION = 10; // (weight of iron ingots in dungeon) / (weight of iron ingots in other chests)
|
private static final int DUNGEON_CHEST_WEIGHT_INFLATION = 10; // (weight of iron ingots in dungeon) / (weight of iron ingots in other chests)
|
||||||
|
|
||||||
|
private DDLoot() { }
|
||||||
|
|
||||||
public static void registerInfo()
|
public static void registerInfo()
|
||||||
{
|
{
|
||||||
DDProperties properties = DDProperties.instance();
|
DDProperties properties = DDProperties.instance();
|
||||||
|
@ -156,4 +161,48 @@ public class DDLoot {
|
||||||
//System.out.println(item.theItemId.getDisplayName() + "\t" + item.itemWeight);
|
//System.out.println(item.theItemId.getDisplayName() + "\t" + item.itemWeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void generateChestContents(ChestGenHooks chestInfo, IInventory inventory, Random random)
|
||||||
|
{
|
||||||
|
//This is a custom version of net.minecraft.util.WeightedRandomChestContent.generateChestContents()
|
||||||
|
//It's designed to avoid the following bugs in MC 1.5:
|
||||||
|
//1. The randomized filling algorithm will sometimes overwrite item stacks with other stacks
|
||||||
|
//2. If multiple enchanted books appear, then they will have the same enchantment
|
||||||
|
|
||||||
|
//The prime number below is used for choosing chest slots in a seemingly-random pattern. Its value
|
||||||
|
//was selected specifically to achieve a spread-out distribution for chests with up to 104 slots.
|
||||||
|
//Choosing a prime number ensures that our increments are relatively-prime to the chest size, which
|
||||||
|
//means we'll cover all the slots before repeating any. This is mathematically guaranteed.
|
||||||
|
final int primeOffset = 239333;
|
||||||
|
|
||||||
|
int count = chestInfo.getCount(random);
|
||||||
|
int size = inventory.getSizeInventory();
|
||||||
|
WeightedRandomChestContent[] content = chestInfo.getItems(random);
|
||||||
|
|
||||||
|
for (int k = 0; k < count; k++)
|
||||||
|
{
|
||||||
|
WeightedRandomChestContent selection = (WeightedRandomChestContent)WeightedRandom.getRandomItem(random, content);
|
||||||
|
|
||||||
|
//Call getChestGenBase() to make sure we generate a different enchantment for books.
|
||||||
|
//Don't just use a condition to check if the item is an instance of ItemEnchantedBook because
|
||||||
|
//we don't know if other mods might add items that also need to be regenerated.
|
||||||
|
selection = selection.theItemId.getItem().getChestGenBase(chestInfo, random, selection);
|
||||||
|
|
||||||
|
ItemStack[] stacks = ChestGenHooks.generateStacks(random, selection.theItemId, selection.theMinimumChanceToGenerateItem, selection.theMaximumChanceToGenerateItem);
|
||||||
|
|
||||||
|
for (ItemStack item : stacks)
|
||||||
|
{
|
||||||
|
int limit = size;
|
||||||
|
int index = random.nextInt(size);
|
||||||
|
|
||||||
|
while (limit > 0 && inventory.getStackInSlot(index) != null)
|
||||||
|
{
|
||||||
|
limit--;
|
||||||
|
index = (index + primeOffset) % size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory.setInventorySlotContents(index, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class SchematicLoader
|
||||||
if (dimList.get(destDimID).dungeonGenerator == null)
|
if (dimList.get(destDimID).dungeonGenerator == null)
|
||||||
{
|
{
|
||||||
//TODO: We should centralize RNG initialization and world-seed modifiers for each specific application.
|
//TODO: We should centralize RNG initialization and world-seed modifiers for each specific application.
|
||||||
final long localSeed = world.getSeed() ^ 0x2F50DB9B4A8057E4L ^ computeDestinationHash(link);
|
final long localSeed = world.getSeed() ^ 0x2F50DB9B4A8057E4L ^ calculateDestinationSeed(link);
|
||||||
final Random random = new Random(localSeed);
|
final Random random = new Random(localSeed);
|
||||||
|
|
||||||
dungeonHelper.generateDungeonLink(link, dungeonHelper.getDimDungeonPack(originDimID), random);
|
dungeonHelper.generateDungeonLink(link, dungeonHelper.getDimDungeonPack(originDimID), random);
|
||||||
|
@ -155,43 +155,50 @@ public class SchematicLoader
|
||||||
return dungeon;
|
return dungeon;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long computeDestinationHash(LinkData link)
|
private static long calculateDestinationSeed(LinkData link)
|
||||||
{
|
{
|
||||||
//Time for some witchcraft.
|
//Time for some witchcraft.
|
||||||
//The code here is inspired by a discussion on Stack Overflow regarding hash codes for 3D.
|
//The code here is inspired by a discussion on Stack Overflow regarding hash codes for 3D.
|
||||||
//Source: http://stackoverflow.com/questions/9858376/hashcode-for-3d-integer-coordinates-with-high-spatial-coherence
|
//Source: http://stackoverflow.com/questions/9858376/hashcode-for-3d-integer-coordinates-with-high-spatial-coherence
|
||||||
|
|
||||||
//Use 8 bits from Y and 24 bits from X and Z. Mix in 8 bits from the destination dim ID too - that means
|
//Use 8 bits from Y and 16 bits from X and Z. Mix in 8 bits from the destination dim ID too - that means
|
||||||
//even if you aligned two doors perfectly between two pockets, it's unlikely they would lead to the same dungeon.
|
//even if you aligned two doors perfectly between two pockets, it's unlikely they would lead to the same dungeon.
|
||||||
|
//We map bits in reverse order to produce more varied RNG output for nearly-identical points. The reason is
|
||||||
|
//that Java's Random outputs the 32 MSBs of its internal state to produce its output. If the differences
|
||||||
|
//between two seeds are small (i.e. in the LSBs), then they will tend to produce similar random outputs anyway!
|
||||||
|
|
||||||
|
//Only bother to assign the 48 least-significant bits since Random only takes those bits from its seed.
|
||||||
|
//NOTE: The casts to long are necessary to get the right results from the bit shifts!!!
|
||||||
|
|
||||||
int bit;
|
int bit;
|
||||||
int index;
|
int index;
|
||||||
long hash;
|
long hash;
|
||||||
int w = link.destDimID;
|
final int w = link.destDimID;
|
||||||
int x = link.destXCoord;
|
final int x = link.destXCoord;
|
||||||
int y = link.destYCoord;
|
final int y = link.destYCoord;
|
||||||
int z = link.destZCoord;
|
final int z = link.destZCoord;
|
||||||
|
|
||||||
hash = 0;
|
hash = 0;
|
||||||
index = 0;
|
index = 48;
|
||||||
for (bit = 0; bit < 8; bit++)
|
for (bit = 0; bit < 8; bit++)
|
||||||
{
|
{
|
||||||
hash |= ((w >> bit) & 1) << index;
|
hash |= (long) ((w >> bit) & 1) << index;
|
||||||
index++;
|
index--;
|
||||||
hash |= ((x >> bit) & 1) << index;
|
hash |= (long) ((x >> bit) & 1) << index;
|
||||||
index++;
|
index--;
|
||||||
hash |= ((y >> bit) & 1) << index;
|
hash |= (long) ((y >> bit) & 1) << index;
|
||||||
index++;
|
index--;
|
||||||
hash |= ((z >> bit) & 1) << index;
|
hash |= (long) ((z >> bit) & 1) << index;
|
||||||
index++;
|
index--;
|
||||||
}
|
}
|
||||||
for (; bit < 24; bit++)
|
for (; bit < 16; bit++)
|
||||||
{
|
{
|
||||||
hash |= ((x >> bit) & 1) << index;
|
hash |= (long) ((x >> bit) & 1) << index;
|
||||||
index++;
|
index--;
|
||||||
hash |= ((z >> bit) & 1) << index;
|
hash |= (long) ((z >> bit) & 1) << index;
|
||||||
index++;
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,9 +10,7 @@ import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.tileentity.TileEntityChest;
|
import net.minecraft.tileentity.TileEntityChest;
|
||||||
import net.minecraft.tileentity.TileEntityDispenser;
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.WeightedRandomChestContent;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.ChestGenHooks;
|
|
||||||
import StevenDimDoors.mod_pocketDim.DDLoot;
|
import StevenDimDoors.mod_pocketDim.DDLoot;
|
||||||
import StevenDimDoors.mod_pocketDim.schematic.WorldOperation;
|
import StevenDimDoors.mod_pocketDim.schematic.WorldOperation;
|
||||||
|
|
||||||
|
@ -42,8 +40,7 @@ public class FillContainersOperation extends WorldOperation
|
||||||
TileEntityChest chest = (TileEntityChest) tileEntity;
|
TileEntityChest chest = (TileEntityChest) tileEntity;
|
||||||
if (isInventoryEmpty(chest))
|
if (isInventoryEmpty(chest))
|
||||||
{
|
{
|
||||||
ChestGenHooks info = DDLoot.DungeonChestInfo;
|
DDLoot.generateChestContents(DDLoot.DungeonChestInfo, chest, random);
|
||||||
WeightedRandomChestContent.generateChestContents(random, info.getItems(random), chest, info.getCount(random));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,22 @@ Exit -> DeadEnd Exit
|
||||||
|
|
||||||
DeadEnd -> DeadEnd Exit
|
DeadEnd -> DeadEnd Exit
|
||||||
|
|
||||||
? ? ? ? ? ? ? ? -> Trap#20 SimpleHall#40 ComplexHall#10 Exit#20 DeadEnd#10
|
? ? ? ? ? ? ? ? ? -> DeadEnd#10 Exit#11 SimpleHall#24 ComplexHall#16 Trap#23 Maze#11
|
||||||
|
|
||||||
? ? ? ? -> Trap#18 SimpleHall#40 ComplexHall#10 Exit#18 DeadEnd#10 Hub#4
|
? ? ? ? ? ? ? ? -> DeadEnd#9 Exit#10 SimpleHall#24 ComplexHall#16 Trap#23 Maze#11 Hub#6
|
||||||
|
|
||||||
? ? ? -> ComplexHall Hub Trap SimpleHall Maze
|
? ? ? ? ? ? ? -> DeadEnd#8 Exit#9 SimpleHall#25 ComplexHall#17 Trap#23 Maze#11 Hub#7
|
||||||
|
|
||||||
? ? -> ComplexHall Hub Trap SimpleHall Maze
|
? ? ? ? ? ? -> DeadEnd#7 Exit#8 SimpleHall#26 ComplexHall#17 Trap#23 Maze#11 Hub#8
|
||||||
|
|
||||||
? -> ComplexHall#40 Hub#30 Trap#10 SimpleHall#10 Maze#10
|
? ? ? ? ? -> DeadEnd#6 Exit#6 SimpleHall#27 ComplexHall#18 Trap#23 Maze#11 Hub#9
|
||||||
|
|
||||||
-> ComplexHall#40 Hub#30 Trap#10 SimpleHall#10 Maze#10
|
? ? ? ? -> DeadEnd#5 Exit#5 SimpleHall#28 ComplexHall#18 Trap#23 Maze#11 Hub#10
|
||||||
|
|
||||||
|
? ? ? -> DeadEnd#3 Exit#3 SimpleHall#29 ComplexHall#19 Trap#23 Maze#11 Hub#11
|
||||||
|
|
||||||
|
? ? -> SimpleHall#9 ComplexHall#8 Trap#17 Maze#23 Hub#44
|
||||||
|
|
||||||
|
? -> SimpleHall#9 ComplexHall#8 Trap#17 Maze#23 Hub#44
|
||||||
|
|
||||||
|
-> SimpleHall#2 ComplexHall#54 Trap#2 Maze#2 Hub#41
|
||||||
|
|
Loading…
Reference in a new issue