Skip to content

Commit

Permalink
Do this instead
Browse files Browse the repository at this point in the history
  • Loading branch information
Nightenom committed Sep 23, 2024
1 parent 6bcfab7 commit 1aa278d
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 42 deletions.
11 changes: 11 additions & 0 deletions src/main/java/com/ldtteam/common/fakelevel/FakeChunk.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public FakeChunk(final FakeLevel<?> worldIn, final int x, final int z)
{
super(worldIn, new ChunkPos(x, z));
this.fakeLevel = worldIn;

// set itself to cache
fakeLevel.lastX = x;
fakeLevel.lastZ = z;
fakeLevel.lastChunk = this;
}

// ========================================
Expand Down Expand Up @@ -217,9 +222,15 @@ public LevelChunkSection[] getSections()
return new LevelChunkSection[0];
}

int lastY;
LevelChunkSection lastSection = null;
@Override
public LevelChunkSection getSection(int yIdx)
{
if (lastY == yIdx && lastSection != null)
{
return lastSection;
}
return new FakeLevelChunkSection(this, yIdx);
}

Expand Down
8 changes: 7 additions & 1 deletion src/main/java/com/ldtteam/common/fakelevel/FakeLevel.java
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,15 @@ public BlockState getBlockState(final BlockPos pos)
return levelSource.isPosInside(pos) ? levelSource.getBlockState(pos) : Blocks.AIR.defaultBlockState();
}

int lastX, lastZ;
ChunkAccess lastChunk = null;
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull)
{
if (lastX == x && lastZ == z && lastChunk != null)
{
return lastChunk;
}
return nonnull || hasChunk(x, z) ? new FakeChunk(this, x, z) : null;
}

Expand Down Expand Up @@ -368,7 +374,7 @@ public boolean isInWorldBounds(final BlockPos pos)
@Override
public CrashReportCategory fillReportDetails(CrashReport report)
{
CrashReportCategory crashreportcategory = report.addCategory("Structurize fake level");
CrashReportCategory crashreportcategory = report.addCategory("BlockUI fake level");
levelSource.describeSelfInCrashReport(crashreportcategory);
return crashreportcategory;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public FakeLevelChunkSection(final FakeChunk fakeChunk, final int yIdx)
super(null, null);
this.fakeChunk = fakeChunk;
this.yIdx = yIdx;

// set itself to cache
fakeChunk.lastY = yIdx;
fakeChunk.lastSection = this;
}

private BlockPos formGlobalPos(int x, int y, int z)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.ldtteam.common.fakelevel;

import net.minecraft.CrashReportCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
Expand All @@ -13,8 +15,6 @@
*/
public class SingleBlockFakeLevelGetter implements IFakeLevelBlockGetter
{
public static final ThreadLocal<FakeLevel<SingleBlockFakeLevelGetter>> THREAD_LOCAL = new ThreadLocal<>();

public BlockState blockState = null;
public BlockEntity blockEntity = null;

Expand Down Expand Up @@ -48,63 +48,59 @@ public int getSizeZ()
return 1;
}

private static void prepareThreadLocal(final Level realLevel)
@Override
public void describeSelfInCrashReport(final CrashReportCategory category)
{
category.setDetail("Single block", blockState::toString);
category.setDetail("Single block entity type",
() -> blockEntity == null ? null : BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(blockEntity.getType()).toString());
}

/**
* Creates simple fakeLevel instance
*
* @param realLevel actual valid vanilla instance to provide eg. registries
* @return new fakeLevel instance
*/
public static FakeLevel<SingleBlockFakeLevelGetter> createSimpleInstance(final Level realLevel)
{
THREAD_LOCAL.set(new FakeLevel<>(new SingleBlockFakeLevelGetter(), IFakeLevelLightProvider.USE_CLIENT_LEVEL, realLevel, null, true));
return new FakeLevel<>(new SingleBlockFakeLevelGetter(), IFakeLevelLightProvider.USE_CLIENT_LEVEL, realLevel, null, true);
}

/**
* Do not forget to unset to prevent potential memory leaks
*
* @param state related to blockEntity
* @param blockState related to blockEntity
* @param blockEntity related to blockState
* @param realLevel actual valid vanilla instance to provide eg. registries
* @return prepared {@link FakeLevel} instance
* @see #unsetThreadLocal()
* @see #unsetThreadLocal(BlockEntity)
* @see #unset(FakeLevel, BlockEntity)
* @see FakeLevel#setEntities(Collection) FakeLevel#setEntities(Collection) if you want to add entities, do not forget to reset
*/
public static FakeLevel<SingleBlockFakeLevelGetter> prepareThreadLocal(final BlockState state,
public static void prepare(final FakeLevel<SingleBlockFakeLevelGetter> fakeLevel,
final BlockState blockState,
@Nullable final BlockEntity blockEntity,
final Level realLevel)
{
final FakeLevel<SingleBlockFakeLevelGetter> level = THREAD_LOCAL.get();
if (level == null)
{
prepareThreadLocal(realLevel);
return prepareThreadLocal(state, blockEntity, realLevel);
}

level.getLevelSource().blockEntity = blockEntity;
level.getLevelSource().blockState = state;
level.setRealLevel(realLevel);
fakeLevel.getLevelSource().blockEntity = blockEntity;
fakeLevel.getLevelSource().blockState = blockState;
fakeLevel.setRealLevel(realLevel);

if (blockEntity != null)
{
blockEntity.setLevel(level);
blockEntity.setLevel(fakeLevel);
}

return level;
}

/**
* @see #prepareThreadLocal(Level)
*/
public static void unsetThreadLocal()
{
unsetThreadLocal(null);
}

/**
* @param blockEntity to unlink level if needed
* @see #prepareThreadLocal(Level)
* @see #prepare(FakeLevel, BlockState, BlockEntity, Level)
*/
public static void unsetThreadLocal(@Nullable final BlockEntity blockEntity)
public static void unset(final FakeLevel<SingleBlockFakeLevelGetter> fakeLevel, @Nullable final BlockEntity blockEntity)
{
final FakeLevel<SingleBlockFakeLevelGetter> level = THREAD_LOCAL.get();
level.getLevelSource().blockEntity = null;
level.getLevelSource().blockState = null;
level.setRealLevel(null);
fakeLevel.getLevelSource().blockEntity = null;
fakeLevel.getLevelSource().blockState = null;
fakeLevel.setRealLevel(null);

if (blockEntity != null)
{
Expand Down
11 changes: 5 additions & 6 deletions src/main/java/com/ldtteam/common/util/BlockToItemHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.ldtteam.blockui.mod.item.BlockStateRenderingData;
import com.ldtteam.common.fakelevel.FakeLevel;
import com.ldtteam.common.fakelevel.IFakeLevelLightProvider;
import com.ldtteam.common.fakelevel.SingleBlockFakeLevelGetter;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
Expand Down Expand Up @@ -60,14 +59,14 @@ public static ItemStack getItemStack(final BlockState blockState, final BlockEnt

if (fakeLevel == null)
{
fakeLevel = new FakeLevel<>(new SingleBlockFakeLevelGetter(), IFakeLevelLightProvider.USE_CLIENT_LEVEL, player.level(), null, true);
fakeLevel = SingleBlockFakeLevelGetter.createSimpleInstance(player.level());
}

fakeLevel.setRealLevel(player.level());
fakeLevel.getLevelSource().blockState = blockState;
fakeLevel.getLevelSource().blockEntity = blockEntity;
SingleBlockFakeLevelGetter.prepare(fakeLevel, blockState, blockEntity, player.level());
final ItemStack result = getItemStackUsingPlayerPick(fakeLevel, BlockPos.ZERO, player, ZERO_POS_HIT_RESULT);
SingleBlockFakeLevelGetter.unset(fakeLevel, blockEntity);

return getItemStackUsingPlayerPick(fakeLevel, BlockPos.ZERO, player, ZERO_POS_HIT_RESULT);
return result;
}

/**
Expand Down

0 comments on commit 1aa278d

Please sign in to comment.