Skip to content

Commit

Permalink
Extend single block FakeLevel
Browse files Browse the repository at this point in the history
  • Loading branch information
Nightenom committed Sep 23, 2024
1 parent a065a4f commit 6bcfab7
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 41 deletions.
6 changes: 3 additions & 3 deletions src/main/java/com/ldtteam/common/fakelevel/FakeLevel.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public BlockPos getWorldPos()

/**
* For better block entity handling in chunk methods. If set then {@link IFakeLevelBlockGetter#getBlockEntity(BlockPos)
* levelSource.getBlockEntity(BlockPos)} is not used
* levelSource.getBlockEntity(BlockPos)} is not used. Reset with empty collection
*
* @param blockEntities all block entities, should be data equivalent to levelSource
*/
Expand All @@ -211,11 +211,11 @@ public void setBlockEntities(final Map<BlockPos, BlockEntity> blockEntities)
}

/**
* @param entities all entities, their level should be this fake level instance
* @param entities all entities, their level should be this fake level instance. Reset with empty collection
*/
public void setEntities(final Collection<? extends Entity> entities)
{
levelEntityGetter = FakeLevelEntityGetterAdapter.ofEntities(entities);
levelEntityGetter = entities.isEmpty() ? FakeLevelEntityGetterAdapter.EMPTY : FakeLevelEntityGetterAdapter.ofEntities(entities);
}

// ========================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import net.minecraft.CrashReportCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
Expand Down Expand Up @@ -126,40 +125,4 @@ default AABB getAABB()
{
return new AABB(getMinX(), getMinBuildHeight(), getMinZ(), getMaxX(), getMaxBuildHeight(), getMaxZ());
}

public static class SingleBlockFakeLevelGetter implements IFakeLevelBlockGetter
{
public BlockState blockState = null;
public BlockEntity blockEntity = null;

@Override
public BlockEntity getBlockEntity(final BlockPos pos)
{
return blockEntity;
}

@Override
public BlockState getBlockState(final BlockPos pos)
{
return blockState;
}

@Override
public int getHeight()
{
return 1;
}

@Override
public int getSizeX()
{
return 1;
}

@Override
public int getSizeZ()
{
return 1;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.ldtteam.common.fakelevel;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;

/**
* Simple implementation of {@link IFakeLevelBlockGetter} mostly for usage in methods where {@link Level} is needed for virtual
* BE/entities etc.
*/
public class SingleBlockFakeLevelGetter implements IFakeLevelBlockGetter
{
public static final ThreadLocal<FakeLevel<SingleBlockFakeLevelGetter>> THREAD_LOCAL = new ThreadLocal<>();

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

@Override
public BlockEntity getBlockEntity(final BlockPos pos)
{
return blockEntity;
}

@Override
public BlockState getBlockState(final BlockPos pos)
{
return blockState;
}

@Override
public int getHeight()
{
return 1;
}

@Override
public int getSizeX()
{
return 1;
}

@Override
public int getSizeZ()
{
return 1;
}

private static void prepareThreadLocal(final Level realLevel)
{
THREAD_LOCAL.set(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 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 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,
@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);

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

return level;
}

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

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

if (blockEntity != null)
{
blockEntity.setLevel(null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.ldtteam.blockui.mod.item.BlockStateRenderingData;
import com.ldtteam.common.fakelevel.FakeLevel;
import com.ldtteam.common.fakelevel.IFakeLevelBlockGetter.SingleBlockFakeLevelGetter;
import com.ldtteam.common.fakelevel.IFakeLevelLightProvider;
import com.ldtteam.common.fakelevel.SingleBlockFakeLevelGetter;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
Expand Down

0 comments on commit 6bcfab7

Please sign in to comment.