Fixed the selection of boundaries for custom dungeons. The code had a
bug that would clip off a portion of dungeons during exporting. Also,
permafabric is not used to mark the edges of the dungeon anymore. That
means dungeons can contain permafabric now without getting cut off, and
the permafabric shells will be included as part of the export.
Changed SchematicLoader so that schematics that have entrances that are
not facing North will still be rotated properly. This involves a
workaround for transformMetadata() since it assumes schematics are
always saved "facing" North.
I've tested this and it's working perfectly, with one exception. If you
create a rift with dd-rift to a dungeon that wasn't saved pointing
North, the rifts sometimes appear beside the player, instead of in the
block where the player's head is. Sometimes you'll appear in the dungeon
facing the right way. Other times, you'll appear inside a wall adjacent
to the entrance or near the entrance facing the wrong way. I have not
managed to narrow down why this happens.
Rotations in SchematicLoader are understandable now. I changed all the
code to use transformPoint() and made sure that the rotations in there
are correct. Testing shows that rooms are being generated correctly. I
also edited portions of the code for clarity and removed some debug
prints. The loading process now allows permafabric to generate - it was
previously converted into regular fabric of reality. For the moment,
the code is stuck to assume that the entry direction is North. I'll
remove that constraint in the next commit.
It turns out my earlier commits didn't completely fix things because
certain implementation details were missing. I had assumed they were
done. Also, some of the information I had regarding the default
schematic orientation was wrong. This commit remedies most of those
problems with a robust rotation implementation. However, I haven't added
the code for linking Warp Doors yet, and there is a bug with tile
entities getting reversed in East/West oriented rooms. Not sure why
that's happening.
It turns out that rotation hadn't been implemented in the code I moved
during my last commit. I've changed things slightly to implement
rotation. I also renamed some coordinate variables to prevent confusion.
Fixed reference to CommandRegenPocket - should be CommandResetDungeons.
Autofixed indentation in SchematicLoader. I wanted to commit that change
before doing any more code changes but I forgot. Then I fixed the code
that calculates the coordinate offsets so our dungeons rotate right. It
was pretty simple - all I had to do was move the xCooe and zCooe
calculations into the loops so they're recalculated to account for
rotation. I rearranged the loops for optimal performance.
Temporarily patched up CommandDeleteAllLinks,
CommandDeleteDimensionData, and CommandDeleteRifts so they'll compile.
I'll be fixing some things for Steven and I'll come back to those
classes to finish overhauling them.
Improved CommandPruneDimensions. Cleaned up the code and improved
performance by using a HashSet instead of an ArrayList to list dimension
reachability. Added an optional argument that sets whether we should
delete the folders of pruned dimensions.
Renamed CommandRegenPocket to CommandResetDungeons. Changed command name
accordingly. Added a message for the user listing the number of dungeons
that were reset. Modified DimHelper slightly to add support for this.
Added error condition if user specifies arguments for the command.
Made progress on overhauling and prettifying our commands. There are
still more changes to be done for this to be functional. I need to do an
intermediate commit because I want to merge in recent changes by Steven.
Improved code in PocketGenerator. Restricted Monolith generation to the
chunk in which populate() is being applied. We should not be generating
Monoliths outside that chunk. Changed condition that would exit the
function if the next available space for a Monolith was above Y = 245.
Exiting the function at that point made no sense.
I've realized that this placement algorithm has probably been patched up
several times and that's resulted in nonsensical code. For instance, the
loop continues as long as you continue finding higher points to place
Monoliths. That would suggest you intended to make columns of them. But
since the loop chooses random columns on each iteration goes back to Y =
0, you're really just jumping around and placing Monoliths in random
places, while using irrelevant checks to decide whether to continue. I
really recommend coming up with a different algorithm. I haven't
replaced it completely in case it would break something.
Cleaned up some of the code in PocketGenerator. Seeded the generation of
Monoliths as a function of the world seed. All of our randomized
selections should be functions of the world seed so people can exchange
seeds with cool DD features. I will rename the file to have proper
capitalization in the next commit. Then I have to fix Monolith spawning.
Also, don't use recursion as a way to loop functions if you could simply
have a loop. I'm referring to the way PocketGenerator.populate() calls
itself. Completely unnecessary.
1. Added converting dungeon type names to lowercase before adding them
to dungeonTypeMapping (a HashMap that associates dungeon type strings
with their lists). Keeping the original casing was causing a
NullPointerException when the HashMap returned null and we expected to
receive a non-null list.
2. Added code to strip out the file extension of a schematic in
validateSchematicName(). The extension was getting dragged along with
the dungeon's weight, which would cause parsing to fail and the name was
considered invalid. This means that none of the custom dungeons were
being registered for generation since the system saw them as badly
tagged. They also wouldn't generate Monoliths even if tagged as closed
because we would ignore the tags.
3. Changed a comparison for the "open" tag to be case insensitive.
4. Minor changes
Fixed the bug that caused "How_to_add_dungeons.txt" to be copied as an
empty file. The reason was very subtle. Also moved the file to a
different directory.
Added a property in our config that enables or disables the Rift Blade's
ability to create new rifts. It can still open existing rifts even if
that ability is disabled. I tested that to be certain. If the ability is
disabled, the Rift Blade blocks on right-click instead of charging like
a bow.
Fixed a small bug. DDProperties.WorldRiftGenerationEnabled is supposed
to control whether rifts and gateways generate outside of Limbo. I
assume that rifts and gateways are always supposed to generate in Limbo
given the wording of that description. However, if the flag was set to
false, we would also disable rift generation in Limbo. I've fixed this
by ignoring that flag if we detect that the chunk is in Limbo.
Partially overhauled our command classes. Added DDCommandBase - it
extends CommandBase and acts as a new base class for our commands. It
removes a little redundancy in our code and provides increased
convenience. Removed the static fields for our commands in
mod_pocketDim. There was no point in keeping them when nothing was using
them. Changed in-game command names to be shorter yet relevant.
Converted all commands to singletons so proper instances can be
retrieved if necessary. Migrated some of the custom dungeon start/ending
logic to DungeonHelper and made customDungeonStatus private. Except for
data objects, we shouldn't be exposing state variables like that without
any kind of checks. I've rewritten the code in some commands but it's
been quite tiring. Still need to fix up lots of things.
Renamed some of the command classes to change "Dim" to "Dimension". I'm
a firm believer in writing most things out except when it would be
absurd. Also deleted CommandPrintDungeonData because it didn't do
anything. We can always add it again if we want it.
Optimized the selection of random dungeons with weights applied. We now
have a class called WeightedContainer for taping into Minecraft's
weighted selection code without having to extend the WeightedRandomItem
class. Using that, we no longer need to keep a list with duplicate
dungeons to achieve weighted selection, so I removed that variable.
Fixed the bug that caused the dungeon creation tutorial to be listed as
a schematic. We were listing all files in the custom schematic directory
as a schematic, even though that file wasn't. I added filtering so that
we only look at files that end with ".schematic". Also improved dungeon
listing by sorting the name list in alphabetical order. That makes the
list much easier to read through.
Added a workaround so that the dungeon list produced by
CommandAddDungeonRift does not have repeated names. Also cleaned up the
code a bit - it's a mess in there. Part of the rewrite eliminated the
bug that caused some dungeon names to be preceded by a backslash (or
slash). I've noticed a different bug now - the dungeon tutorial file is
being included in the list of dungeons. I'll be fixing that in the next
commit.
Added checks for the material that a gateway is being built upon. Now
gateways no longer generate on top of trees. Combined with multiple
generation attempts, there is a good chance that they will find a gap
between trees to generate at ground level. I also added checks to stop
gateways and rifts from generating on top of the Nether's bedrock.
I fixed a subtle bug in RiftGenerator. The code for picking random
coordinates on the surface of a chunk would subtract a random amount
from the coordinate of the chunk's corner. Unfortunately, subtracting
meant that we would almost always generate coordinates OUTSIDE the
intended chunk. The correct calculation was to add, not subtract. This
meant that if you walked in a direction in which our gateways were
generated outside of existing chunks, then their data would be lost and
no gateways would generate!
To reproduce this bug, max out the chance of generating gateways and fly
in the direction that decreases X and Z. You must fly into new chunks.
After passing the gateways produced when you spawn (if this is a new
world) you'll see that gateways don't generate on the landscape.
However, if you change directions, they'll begin generating again.
In addition to fixing that bug, I also tweaked all the block setting
calls in RiftGenerator so that they'll trigger block updates and send
update packets to the client. I think triggering block updates will
prevent unusual problems with floating sand, gravel, etc.
Added a loop that allows RiftGenerator to retry generating a gateway if
it picks an invalid location for it. It has a limited number of tries
before it gives up and doesn't generate a gateway. I haven't added the
logic for avoiding generating on top of trees, but that'll be easy to
add now.
Overhauled RIftGenerator. The code is significantly more readable now.
It's commented and much more compact. I also removed all fields from
RiftGenerator - they were unnecessary and using them increased the risk
of buggy code. Made the code rely solely on the Random instance provided
by MC, meaning our rifts and gateways will be tied to the world seed.
Tweaked the code slightly so that clusters of rifts and gateways can
never generate in the same chunk. This was previously possible, although
highly unlikely. It's a work of art now. <3
Replaced all instances of Hashtable in our code with HashMap. I had
never given that much thought until Steven mentioned it. HashMap is a
better alternative for our code.
Tweaked the code that copies the dungeon export tutorial. I'm not sure
it worked all the time before. It didn't seem quite right. I've
confirmed it's working better now. Also cleaned up copyfile a little.
Although fields were created in DDProperties for Monolith spawning and
Rift generation, they were mislabeled as reading the "World Rift
Generation Enabled" property. I gave them proper names. I also changed
the fields and names to be more intuitive and rewrote the descriptions.
For instance, "MonolithSpawnDensity" is a misnomer because as density
increases, there should be more Monoliths, not less. Now the properties
clearly state how they affect a feature. I rewrote the conditions that
used each property to correspond with those simplified descriptions and
gave the properties default values that will match the generation rates
seen before.
I also made the rift generation code less cryptic and fixed a bug; there
was a check that compared if a dimension was a pocket dimension by its
name to prevent rift generation. That name check was wrong - it would
never work. Now we check if the provider is an instance of
pocketProvider. That will continue working even if we change the way
that pocket dimensions are named.
Separated exportDungeon() from registerCustomDungeon() - exporting a
dungeon no longer automatically registers it. Also changed
exportDungeon() so that it returns a boolean indicating success or
failure, instead of an instance of DungeonGenerator that was never being
used. I modified CommandEndDungeonCreation so that it can warn you if
exporting the dungeon failed (if exportDungeon() returned false), and
also, to register the dungeon after it's exported since it's no longer
automatic.
Removed a line in CommandEndDungeonCreation that inserted a new dungeon
directly into DungeonHelper.customDungeons. This had a chance of causing
a duplicate listing. registerCustomDungeon() was already being invoked
before and if reading tags from the file name failed, the dungeon would
get added twice. This could explain some of the buggy dungeon listing
that would appear during testing.
Changed the function to use a Hashtable mapping dungeon types to their
respective lists so that it wouldn't be necessary to hardcode a
condition for each type. The code is much shorter now and we can add new
types with ease. The next stage will be to remove
weightedDungeonGetList, if possible, so that we don't have to construct
a list with duplicates just to have weights. The loop that repeatedly
inserted dungeons into that list has been removed anyway, but it
shouldn't affect anything since custom dungeon integration was broken
and weights were being ignored.
I changed the name filter for schematic names from
CommandEndDungeonCreation to DungeonHelper, and renamed it to
NamePattern. I also rewrote most of registerCustomDungeon() to be much
more concise. The changes are incomplete but I'm making an intermediate
commit. The aim is to change DungeonHelper into a proper singleton and
to eliminate the clunky sections that manually map dungeon categories to
their corresponding lists. Instead, I'll use data structures to
implement that far more efficiently.
Set various lists of DungeonGenerators to private - there was no need to
make them public fields. While cleaning up the code before, I
accidentally erased the default constructor, which handled loading a
reference to DDProperties. I've put the code back in so that the class
works correctly.
I was able to infer that HashMap schematic should have generic
parameters <String, Tag> and changed the declaration accordingly. All
generic collections in DungeonHelper are now parameterized properly.
Cleaned up the indentation and empty lines in DungeonHelper. Set
metadataFlipList and metadataNextList to have generic type Integer,
since they're used to store block IDs. Whenever possible, we should
always be using parameterized collections instead of leaving their types
unspecified. I'd like to fix up the schematic HashMap in the future -
unless it's necessary, we shouldn't be storing values of various types
in that collection. Strongly typed variables or a class with the
appropriate fields would be much cleaner.
Changed the formatting in DungeonGenerator. Autocorrected indentation
and removed extra empty lines to improve readability. None of the
variables were changed since that would break compability with previous
serialized instances.
Changed SchematicLoader to use DDLoot.DungeonChestInfo instead of
requesting a reference to the same data through ChestGenHooks. Exactly
the same data is being retrieved, but ChestGenHooks retrieves it by
performing a lookup on a map relating loot categories to loot info, so
it's slightly slower. No point in doing that if we have access to the
reference directly.
Decreased the weight of DD items very slightly to make them a little
more rare. Added a section to DDLoot.mergeCategories() that searches for
the enchanted book loot and fixes its weight to 3 (instead of the usual
1). This makes enchanted books slightly more common. I confirmed that
books are actually spawning in loot chests. There is the possibility
that there is a built-in chance of an enchanted book taking up a chest
slot but not actually generating anything.