Conversation
|
|
||
| @Override | ||
| public void loadData(CompoundTag compoundTag) { | ||
| GlobalPos.CODEC.parse(NbtOps.INSTANCE, compoundTag).result().ifPresent(globalPos -> data = globalPos); |
There was a problem hiding this comment.
saveData saves to compoundTag "spawn", but loadData tries to load from root rather than the compoundTag. This silently fails, and the code will end up doing the whole finding valid spawn chunks as if it's a first boot. This usually works but by accident and it can fail in interesting ways.
Try this
@Override
public void loadData(CompoundTag compoundTag) {
GlobalPos.CODEC.parse(NbtOps.INSTANCE, compoundTag.get("spawn")).result().ifPresent(globalPos -> data = globalPos);
}|
|
||
| public static void setSpawnPos(ServerLevel level, GlobalPos globalPos) { | ||
| CustomSpawnSaveHandler handler = read(level); | ||
| handler.data = globalPos; |
There was a problem hiding this comment.
This is where handler.setDirty() goes; you set a field dirty any time you change it from its saved value. That only happens in this method
| //This probably doesn't need to always be true, I just don't know enough about it | ||
| @Override | ||
| public boolean isDirty() { | ||
| return true; |
There was a problem hiding this comment.
See above, don't need this bit, just mark dirty whenever you change the data from what is stored
|
|
||
| /** | ||
| * @author | ||
| * @reason It was becoming too complicated to do as a normal mixin. |
There was a problem hiding this comment.
If you want this more targeted rather than an overwrite, it would look something like this:
@Redirect(method = "onCreateWorldSpawn", at = @At(value = "INVOKE", target = "Lnet/dries007/tfc/world/ChunkGeneratorExtension;findSpawnBiome(Lnet/minecraft/util/RandomSource;)Lnet/minecraft/core/BlockPos;", remap = true))
private static BlockPos tfg$findSpawnBiome(ChunkGeneratorExtension extension, RandomSource random, @Local(name = "level") ServerLevel level) {
RegionGenerator regionGen = new RegionGenerator(extension.settings(), random);
var condition = CustomSpawnHelper.getFromConfig();
boolean climateMatch = false;
int seedTicker = 0;
BlockPos pos = null;
ChunkPos chunkPos;
while (!climateMatch) {
pos = CustomSpawnHelper.findSpawnBiome(condition.spawnCenterX(), condition.spawnCenterZ(), extension.settings().spawnDistance() * condition.spawnRadiusMultiplier(), random, extension);
chunkPos = new ChunkPos(pos);
Region.Point regionPoint = regionGen.getOrCreateRegionPoint(Units.blockToGrid(chunkPos.getMinBlockX()), Units.blockToGrid(chunkPos.getMinBlockZ()));
System.out.println("Testing chunkPos " + chunkPos.getWorldPosition());
System.out.println(regionPoint.temperature);
System.out.println(regionPoint.rainfall);
if (CustomSpawnHelper.testWithinRanges(regionPoint.temperature, regionPoint.rainfall, condition)) {
climateMatch = true;
} else {
++seedTicker;
random = new XoroshiroRandomSource(level.getSeed() + seedTicker);
}
}
return pos;
}
@Inject(method = "onCreateWorldSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/event/level/LevelEvent$CreateSpawnPosition;setCanceled(Z)V"))
private static void tfg$saveSpawnPos(LevelEvent.CreateSpawnPosition event, CallbackInfo ci, @Local(name = "level") ServerLevel level, @Local(name = "levelData") ServerLevelData leveldata) {
var condition = CustomSpawnHelper.getFromConfig();
BlockPos spawnPos = new BlockPos(leveldata.getXSpawn(), leveldata.getYSpawn(), leveldata.getZSpawn());
GlobalPos globalSpawnPos = GlobalPos.of(ServerLevel.OVERWORLD, spawnPos);
if (condition.dimension() == ServerLevel.OVERWORLD) {
CustomSpawnSaveHandler.setSpawnPos(level, globalSpawnPos);
} else if (condition.dimension() == ServerLevel.NETHER) {
CustomSpawnSaveHandler.setSpawnPos(level, CustomSpawnHelper.BENEATH_PLACEHOLDER);
} else if (condition.dimension() == Planet.MARS) {
CustomSpawnSaveHandler.setSpawnPos(level, CustomSpawnHelper.MARS_PLACEHOLDER);
}
CustomSpawnHelper.resetConfigValue();
}Specifically injecting on the spawn biome search, and at the end to do the save. It's more obvious what has changed this way though the overwrite is fine too
| BlockPos found = null; | ||
| int count = 0; | ||
|
|
||
| for (int radius = maxRadius; radius <= maxRadius; radius += step) { |
There was a problem hiding this comment.
The outer loop never iterates, because radius starts at maxRadius. Is that intentional? Can either remove the outer loop, or start close in and loop outwards if that's what you want
| } | ||
|
|
||
| if (condition.dimension() == ServerLevel.OVERWORLD) { | ||
| CustomSpawnSaveHandler.setSpawnPos(level, globalSpawnPos); |
There was a problem hiding this comment.
If globalSpawnPos is null then this will cause a NPE when you getSpawnPos.
TFC doesn't have this issue because they do levelData.setSpawn(chunkPos.getWorldPosition().offset(8, generator.getSpawnHeight(level), 8), 0.0F); earlier as a rough first pass. Could do a similar fallback like that for globalSpawnPos by initiating it to that instead of null.
Don't merge.