Remesh chunks on the client when changing the blockstate
And slim down the code a bit
This commit is contained in:
parent
871c3ac54e
commit
f2a60f4e8e
@ -14,7 +14,6 @@ Template blocks can be placed in the world, then right-clicked with a full-size
|
|||||||
|
|
||||||
# quat was here - TODO
|
# quat was here - TODO
|
||||||
|
|
||||||
* Schedule chunk rerenders when a player edits a template block :sweat_smile:
|
|
||||||
* Re-generalize the model system (I removed a layer of indirection while rewriting it, so it's just slopes now)
|
* Re-generalize the model system (I removed a layer of indirection while rewriting it, so it's just slopes now)
|
||||||
* See what I can do about using the vanilla rotation system (`ModelBakeSettings.getRotation`) instead of manually rotating the `Mesh`
|
* See what I can do about using the vanilla rotation system (`ModelBakeSettings.getRotation`) instead of manually rotating the `Mesh`
|
||||||
* A simplification of the mesh system would *definitely* reduce the friction of adding new meshes
|
* A simplification of the mesh system would *definitely* reduce the friction of adding new meshes
|
||||||
|
@ -1,27 +1,34 @@
|
|||||||
package io.github.cottonmc.templates;
|
package io.github.cottonmc.templates;
|
||||||
|
|
||||||
import io.github.cottonmc.templates.block.SlopeBlock;
|
import io.github.cottonmc.templates.block.SlopeBlock;
|
||||||
import io.github.cottonmc.templates.block.entity.SlopeEntity;
|
import io.github.cottonmc.templates.block.entity.TemplateEntity;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.entity.BlockEntityType;
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class Templates implements ModInitializer {
|
public class Templates implements ModInitializer {
|
||||||
public static final String MODID = "templates";
|
public static final String MODID = "templates";
|
||||||
|
|
||||||
public static final Block SLOPE = Registry.register(Registries.BLOCK, id("slope"), new SlopeBlock());
|
public static final Block SLOPE = Registry.register(Registries.BLOCK, id("slope"), new SlopeBlock());
|
||||||
public static final BlockEntityType<SlopeEntity> SLOPE_ENTITY = Registry.register(
|
public static final BlockEntityType<TemplateEntity> SLOPE_ENTITY = Registry.register(
|
||||||
Registries.BLOCK_ENTITY_TYPE,
|
Registries.BLOCK_ENTITY_TYPE, id("slope"),
|
||||||
id("slope"),
|
FabricBlockEntityTypeBuilder.create(Templates::makeSlopeEntity, SLOPE).build(null)
|
||||||
FabricBlockEntityTypeBuilder.create(SlopeEntity::new, SLOPE).build(null)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Overridden in TemplatesClient
|
||||||
|
public static BiConsumer<World, BlockPos> chunkRerenderProxy = (world, pos) -> {};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
Registry.register(Registries.ITEM, id("slope"), (Item) new BlockItem(SLOPE, new Item.Settings()));
|
Registry.register(Registries.ITEM, id("slope"), (Item) new BlockItem(SLOPE, new Item.Settings()));
|
||||||
@ -30,4 +37,9 @@ public class Templates implements ModInitializer {
|
|||||||
public static Identifier id(String path) {
|
public static Identifier id(String path) {
|
||||||
return new Identifier(MODID, path);
|
return new Identifier(MODID, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//simply for breaking the circular reference in the SLOPE_ENTITY constructor call
|
||||||
|
private static TemplateEntity makeSlopeEntity(BlockPos pos, BlockState state) {
|
||||||
|
return new TemplateEntity(SLOPE_ENTITY, pos, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,9 @@ import io.github.cottonmc.templates.model.TemplateModelVariantProvider;
|
|||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
||||||
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.util.math.ChunkSectionPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
|
|
||||||
public class TemplatesClient implements ClientModInitializer {
|
public class TemplatesClient implements ClientModInitializer {
|
||||||
@ -14,6 +16,16 @@ public class TemplatesClient implements ClientModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
|
Templates.chunkRerenderProxy = (world, pos) -> {
|
||||||
|
if(world == MinecraftClient.getInstance().world) {
|
||||||
|
MinecraftClient.getInstance().worldRenderer.scheduleBlockRender(
|
||||||
|
ChunkSectionPos.getSectionCoord(pos.getX()),
|
||||||
|
ChunkSectionPos.getSectionCoord(pos.getY()),
|
||||||
|
ChunkSectionPos.getSectionCoord(pos.getZ())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> provider);
|
ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> provider);
|
||||||
provider.registerTemplateModels2(Templates.SLOPE, Templates.SLOPE.getDefaultState().with(SlopeBlock.FACING, Direction.SOUTH), SlopeUnbakedModel::new);
|
provider.registerTemplateModels2(Templates.SLOPE, Templates.SLOPE.getDefaultState().with(SlopeBlock.FACING, Direction.SOUTH), SlopeUnbakedModel::new);
|
||||||
|
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
package io.github.cottonmc.templates.block.entity;
|
|
||||||
|
|
||||||
import io.github.cottonmc.templates.Templates;
|
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
|
|
||||||
public class SlopeEntity extends TemplateEntity {
|
|
||||||
public SlopeEntity(BlockPos pos, BlockState state) {
|
|
||||||
super(Templates.SLOPE_ENTITY, pos, state, Templates.SLOPE);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +1,45 @@
|
|||||||
package io.github.cottonmc.templates.block.entity;
|
package io.github.cottonmc.templates.block.entity;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
import io.github.cottonmc.templates.Templates;
|
||||||
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity;
|
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity;
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
import net.minecraft.block.entity.BlockEntityType;
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.nbt.NbtHelper;
|
import net.minecraft.nbt.NbtHelper;
|
||||||
import net.minecraft.network.listener.ClientPlayPacketListener;
|
import net.minecraft.network.listener.ClientPlayPacketListener;
|
||||||
import net.minecraft.network.packet.Packet;
|
import net.minecraft.network.packet.Packet;
|
||||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class TemplateEntity extends BlockEntity implements RenderAttachmentBlockEntity {
|
public class TemplateEntity extends BlockEntity implements RenderAttachmentBlockEntity {
|
||||||
protected BlockState renderedState = Blocks.AIR.getDefaultState();
|
protected BlockState renderedState = Blocks.AIR.getDefaultState();
|
||||||
protected boolean glowstone = false;
|
protected boolean glowstone = false;
|
||||||
protected boolean redstone = false;
|
protected boolean redstone = false;
|
||||||
private final Block baseBlock;
|
|
||||||
|
|
||||||
public TemplateEntity(BlockEntityType<?> type, BlockPos pos, BlockState state, Block baseBlock) {
|
public TemplateEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
this.baseBlock = baseBlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readNbt(NbtCompound tag) {
|
public void readNbt(NbtCompound tag) {
|
||||||
super.readNbt(tag);
|
super.readNbt(tag);
|
||||||
|
|
||||||
|
BlockState lastRenderedState = renderedState;
|
||||||
|
|
||||||
renderedState = NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), tag.getCompound("BlockState"));
|
renderedState = NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), tag.getCompound("BlockState"));
|
||||||
glowstone = tag.getBoolean("Glowstone");
|
glowstone = tag.getBoolean("Glowstone");
|
||||||
redstone = tag.getBoolean("Redstone");
|
redstone = tag.getBoolean("Redstone");
|
||||||
if(world != null && world.isClient) {
|
|
||||||
//TODO probably unsafe, i think the method was removed in 1.14.4 or something though
|
//Force a chunk remesh on the client, if the displayed blockstate has changed
|
||||||
// i cant find any relevant method that takes only 1 blockpos argument
|
if(world != null && world.isClient && !Objects.equals(lastRenderedState, renderedState)) {
|
||||||
((ClientWorld) world).scheduleBlockRenders(pos.getX(), pos.getY(), pos.getZ());
|
Templates.chunkRerenderProxy.accept(world, pos);
|
||||||
//world.scheduleBlockRender(pos);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,13 +69,7 @@ public abstract class TemplateEntity extends BlockEntity implements RenderAttach
|
|||||||
|
|
||||||
public void change() {
|
public void change() {
|
||||||
markDirty();
|
markDirty();
|
||||||
if(world != null && !world.isClient) {
|
if(world instanceof ServerWorld sworld) sworld.getChunkManager().markForUpdate(pos); //dispatch to clients
|
||||||
//for(ServerPlayerEntity player : PlayerLookup.tracking(this)) player.networkHandler.sendPacket(this.toUpdatePacket());
|
|
||||||
|
|
||||||
//TODO is this needed
|
|
||||||
//world.updateNeighborsAlways(pos.offset(Direction.UP), baseBlock);
|
|
||||||
world.updateListeners(pos, getCachedState(), getCachedState(), 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockState getRenderedState() {
|
public BlockState getRenderedState() {
|
||||||
@ -106,6 +99,9 @@ public abstract class TemplateEntity extends BlockEntity implements RenderAttach
|
|||||||
public void setRedstone(boolean newRedstone) {
|
public void setRedstone(boolean newRedstone) {
|
||||||
boolean lastRedstone = redstone;
|
boolean lastRedstone = redstone;
|
||||||
redstone = newRedstone;
|
redstone = newRedstone;
|
||||||
if(lastRedstone != newRedstone) change();
|
if(lastRedstone != newRedstone) {
|
||||||
|
world.updateNeighbors(pos, getCachedState().getBlock());
|
||||||
|
change();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user