diff --git a/src/main/java/com/thebrokenrail/energonrelics/EnergonRelics.java b/src/main/java/com/thebrokenrail/energonrelics/EnergonRelics.java index 6a18660..7babcf4 100644 --- a/src/main/java/com/thebrokenrail/energonrelics/EnergonRelics.java +++ b/src/main/java/com/thebrokenrail/energonrelics/EnergonRelics.java @@ -3,6 +3,7 @@ package com.thebrokenrail.energonrelics; import com.thebrokenrail.energonrelics.block.BlockBreakerBlock; import com.thebrokenrail.energonrelics.block.CreativeEnergySourceBlock; import com.thebrokenrail.energonrelics.block.DefensiveLaserBlock; +import com.thebrokenrail.energonrelics.block.HolographicSkyBlock; import com.thebrokenrail.energonrelics.block.LightningRodBlock; import com.thebrokenrail.energonrelics.block.VeridiumBlockBlock; import com.thebrokenrail.energonrelics.block.forcefield.ForcefieldBlock; @@ -92,6 +93,8 @@ public class EnergonRelics implements ModInitializer { public static final CreativeEnergySourceBlock CREATIVE_ENERGY_SOURCE_BLOCK = new CreativeEnergySourceBlock(); + public static final HolographicSkyBlock HOLOGRAPHIC_SKY_BLOCK = new HolographicSkyBlock(); + @Override public void onInitialize() { NETWORK_CHIP_ITEM = Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "network_chip"), new NetworkChipItem()); @@ -139,6 +142,8 @@ public class EnergonRelics implements ModInitializer { Registry.register(Registry.SOUND_EVENT, BEEP_SOUND_ID, BEEP_SOUND_EVENT); CREATIVE_ENERGY_SOURCE_BLOCK.register("creative_energy_source"); + + HOLOGRAPHIC_SKY_BLOCK.register("holographic_sky"); } public static void playBeep(World world, BlockPos pos) { diff --git a/src/main/java/com/thebrokenrail/energonrelics/block/HolographicSkyBlock.java b/src/main/java/com/thebrokenrail/energonrelics/block/HolographicSkyBlock.java new file mode 100644 index 0000000..0d4e283 --- /dev/null +++ b/src/main/java/com/thebrokenrail/energonrelics/block/HolographicSkyBlock.java @@ -0,0 +1,71 @@ +package com.thebrokenrail.energonrelics.block; + +import com.thebrokenrail.energonrelics.block.entity.HolographicSkyBlockEntity; +import com.thebrokenrail.energonrelics.block.util.energy.EnergyProviderBlock; +import com.thebrokenrail.energonrelics.client.block.entity.render.DefensiveLaserBlockEntityRenderer; +import com.thebrokenrail.energonrelics.client.block.entity.render.HolographicSkyBlockEntityRenderer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.minecraft.block.Block; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ShapeContext; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.sound.BlockSoundGroup; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.BooleanProperty; +import net.minecraft.state.property.IntProperty; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; + +import java.util.function.Function; + +@SuppressWarnings("deprecation") +public class HolographicSkyBlock extends EnergyProviderBlock { + public static final BooleanProperty POWERED = Properties.POWERED; + public static final IntProperty LIGHT_LEVEL = IntProperty.of("light_level", 0, 15); + + public HolographicSkyBlock() { + super(FabricBlockSettings.copy(Blocks.OBSIDIAN).sounds(BlockSoundGroup.GLASS).nonOpaque().allowsSpawning((state, world, pos, type) -> !state.get(POWERED)).solidBlock((state, world, pos) -> !state.get(POWERED)).suffocates((state, world, pos) -> !state.get(POWERED)).lightLevel(state -> state.get(POWERED) ? 7 : 0).blockVision((state, world, pos) -> !state.get(POWERED))); + setDefaultState(getDefaultState().with(POWERED, false).with(LIGHT_LEVEL, 0)); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(POWERED, LIGHT_LEVEL); + } + + @Override + public boolean isTranslucent(BlockState state, BlockView world, BlockPos pos) { + return true; + } + + @Override + public VoxelShape getVisualShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + return VoxelShapes.empty(); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return state.get(POWERED) ? BlockRenderType.ENTITYBLOCK_ANIMATED : BlockRenderType.MODEL; + } + + @Override + protected Function, BlockEntity> getFactory() { + return HolographicSkyBlockEntity::new; + } + + @Override + @Environment(EnvType.CLIENT) + protected Function> getRenderer() { + return HolographicSkyBlockEntityRenderer::new; + } +} diff --git a/src/main/java/com/thebrokenrail/energonrelics/block/entity/HolographicSkyBlockEntity.java b/src/main/java/com/thebrokenrail/energonrelics/block/entity/HolographicSkyBlockEntity.java new file mode 100644 index 0000000..27b3c4a --- /dev/null +++ b/src/main/java/com/thebrokenrail/energonrelics/block/entity/HolographicSkyBlockEntity.java @@ -0,0 +1,48 @@ +package com.thebrokenrail.energonrelics.block.entity; + +import com.thebrokenrail.energonrelics.block.HolographicSkyBlock; +import com.thebrokenrail.energonrelics.config.HardcodedConfig; +import com.thebrokenrail.energonrelics.energy.core.EnergyReceiverBlockEntity; +import com.thebrokenrail.energonrelics.energy.core.util.Action; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.Block; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.LightType; + +public class HolographicSkyBlockEntity extends EnergyReceiverBlockEntity { + public HolographicSkyBlockEntity(BlockEntityType type) { + super(type); + } + + @Override + protected void tickEnergy() { + addAction(Action.createBlockStatePropertyAction(HardcodedConfig.HOLOGRAPHIC_SKY_ENERGY_REQUIRED, HolographicSkyBlock.POWERED, true, false)); + + assert getWorld() != null; + + int newLightLevel; + if (getCachedState().get(HolographicSkyBlock.POWERED)) { + newLightLevel = getWorld().getLightLevel(LightType.SKY, new BlockPos(getPos().getX(), 1024, getPos().getZ())) - getWorld().getAmbientDarkness(); + } else { + newLightLevel = 0; + } + + int oldLightLevel = getCachedState().get(HolographicSkyBlock.LIGHT_LEVEL); + + if (oldLightLevel != newLightLevel) { + getWorld().setBlockState(getPos(), getCachedState().with(HolographicSkyBlock.LIGHT_LEVEL, newLightLevel)); + } + } + + @Environment(EnvType.CLIENT) + public boolean shouldDrawSide(Direction direction) { + if (getWorld() != null) { + return Block.shouldDrawSide(getCachedState(), getWorld(), getPos(), direction); + } else { + return true; + } + } +} diff --git a/src/main/java/com/thebrokenrail/energonrelics/client/block/entity/render/HolographicSkyBlockEntityRenderer.java b/src/main/java/com/thebrokenrail/energonrelics/client/block/entity/render/HolographicSkyBlockEntityRenderer.java new file mode 100644 index 0000000..1c5cd72 --- /dev/null +++ b/src/main/java/com/thebrokenrail/energonrelics/client/block/entity/render/HolographicSkyBlockEntityRenderer.java @@ -0,0 +1,105 @@ +package com.thebrokenrail.energonrelics.client.block.entity.render; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.thebrokenrail.energonrelics.EnergonRelics; +import com.thebrokenrail.energonrelics.block.HolographicSkyBlock; +import com.thebrokenrail.energonrelics.block.entity.HolographicSkyBlockEntity; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderPhase; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Matrix4f; + +@Environment(EnvType.CLIENT) +public class HolographicSkyBlockEntityRenderer extends HighlightBlockEntityRenderer { + @SuppressWarnings("deprecation") + private static final RenderPhase.Target SKY_TARGET = new RenderPhase.Target("fasterthanc_sky_target", () -> { + RenderSystem.pushMatrix(); + RenderSystem.enableTexture(); + WorldWithSky worldWithSky = (WorldWithSky) MinecraftClient.getInstance().worldRenderer; + worldWithSky.getSky().beginRead(); + }, () -> { + WorldWithSky worldWithSky = (WorldWithSky) MinecraftClient.getInstance().worldRenderer; + worldWithSky.getSky().endRead(); + RenderSystem.popMatrix(); + }); + @SuppressWarnings("deprecation") + private static final RenderPhase.Texturing SKY_TEXTURING = new RenderPhase.Texturing("fasterthanc_sky_texturing", () -> { + RenderSystem.pushMatrix(); + RenderSystem.matrixMode(5890); + RenderSystem.pushMatrix(); + RenderSystem.loadIdentity(); + RenderSystem.translatef(0.5F, 0.5F, 0.0F); + RenderSystem.scalef(0.5F, 0.5F, 1.0F); + RenderSystem.mulTextureByProjModelView(); + RenderSystem.matrixMode(5888); + RenderSystem.setupEndPortalTexGen(); + }, () -> { + RenderSystem.matrixMode(5890); + RenderSystem.popMatrix(); + RenderSystem.matrixMode(5888); + RenderSystem.clearTexGen(); + RenderSystem.popMatrix(); + }); + + public interface WorldWithSky { + Framebuffer getSky(); + } + + public HolographicSkyBlockEntityRenderer(BlockEntityRenderDispatcher dispatcher) { + super(dispatcher); + } + + private static RenderLayer getLayer() { + return RenderLayer.of(EnergonRelics.NAMESPACE + ":holographic_sky", VertexFormats.POSITION_COLOR, 7, 256, false, true, RenderLayer.MultiPhaseParameters.builder().target(SKY_TARGET).texturing(SKY_TEXTURING).build(false)); + } + + private static final RenderLayer LAYER = getLayer(); + + @Override + public void render(BlockEntity entity, float f, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, int j) { + if (entity instanceof HolographicSkyBlockEntity && entity.getCachedState().get(HolographicSkyBlock.POWERED)) { + matrixStack.push(); + float g = getHeight(); + Matrix4f matrix4f = matrixStack.peek().getModel(); + renderLayer((HolographicSkyBlockEntity) entity, g, matrix4f, vertexConsumerProvider.getBuffer(LAYER)); + matrixStack.pop(); + } + super.render(entity, f, matrixStack, vertexConsumerProvider, i, j); + } + + private void renderLayer(HolographicSkyBlockEntity entity, float f, Matrix4f matrix4f, VertexConsumer vertexConsumer) { + float h = 1f; + float i = 1f; + float j = 1f; + renderSide(entity, matrix4f, vertexConsumer, 0.0F, 1.0F, 0.0F, 1.0F, 1.0F, 1.0F, 1.0F, 1.0F, h, i, j, Direction.SOUTH); + renderSide(entity, matrix4f, vertexConsumer, 0.0F, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, h, i, j, Direction.NORTH); + renderSide(entity, matrix4f, vertexConsumer, 1.0F, 1.0F, 1.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.0F, h, i, j, Direction.EAST); + renderSide(entity, matrix4f, vertexConsumer, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 1.0F, 1.0F, 0.0F, h, i, j, Direction.WEST); + renderSide(entity, matrix4f, vertexConsumer, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 1.0F, h, i, j, Direction.DOWN); + renderSide(entity, matrix4f, vertexConsumer, 0.0F, 1.0F, f, f, 1.0F, 1.0F, 0.0F, 0.0F, h, i, j, Direction.UP); + } + + private void renderSide(HolographicSkyBlockEntity entity, Matrix4f matrix4f, VertexConsumer vertexConsumer, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p, Direction side) { + if (entity.shouldDrawSide(side)) { + vertexConsumer.vertex(matrix4f, f, h, j).color(n, o, p, 1.0F).next(); + vertexConsumer.vertex(matrix4f, g, h, k).color(n, o, p, 1.0F).next(); + vertexConsumer.vertex(matrix4f, g, i, l).color(n, o, p, 1.0F).next(); + vertexConsumer.vertex(matrix4f, f, i, m).color(n, o, p, 1.0F).next(); + } + } + + protected float getHeight() { + return 1f; + } +} \ No newline at end of file diff --git a/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java b/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java index 7676129..ddc5601 100644 --- a/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java +++ b/src/main/java/com/thebrokenrail/energonrelics/config/HardcodedConfig.java @@ -30,4 +30,6 @@ public class HardcodedConfig { public static final long FORCEFIELD_PROJECTOR_ENERGY_REQUIRED = 64; public static final int FORCEFIELD_MAX_SIZE = 12; + + public static final long HOLOGRAPHIC_SKY_ENERGY_REQUIRED = 15; } \ No newline at end of file diff --git a/src/main/java/com/thebrokenrail/energonrelics/mixin/MixinWorldRenderer.java b/src/main/java/com/thebrokenrail/energonrelics/mixin/MixinWorldRenderer.java new file mode 100644 index 0000000..bcb4036 --- /dev/null +++ b/src/main/java/com/thebrokenrail/energonrelics/mixin/MixinWorldRenderer.java @@ -0,0 +1,61 @@ +package com.thebrokenrail.energonrelics.mixin; + +import com.thebrokenrail.energonrelics.client.block.entity.render.HolographicSkyBlockEntityRenderer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Matrix4f; +import org.lwjgl.opengl.GL30; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Environment(EnvType.CLIENT) +@Mixin(WorldRenderer.class) +public class MixinWorldRenderer implements HolographicSkyBlockEntityRenderer.WorldWithSky { + @Shadow + @Final + private MinecraftClient client; + + @Unique + private Framebuffer sky; + + @Override + public Framebuffer getSky() { + return sky; + } + + @Inject(at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V", args = "ldc=fog"), method = "render", allow = 1) + public void render(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo info) { + Framebuffer mcFb = client.getFramebuffer(); + + if (sky == null) { + sky = new Framebuffer(mcFb.viewportWidth, mcFb.viewportHeight, true, true); + } else if (sky.viewportWidth != mcFb.viewportWidth || sky.viewportHeight != mcFb.viewportHeight) { + sky.initFbo(mcFb.viewportWidth, mcFb.viewportHeight, true); + } + + blit(mcFb, sky); + + mcFb.beginWrite(false); + } + + @Unique + private void blit(Framebuffer from, Framebuffer into) { + GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, from.fbo); + GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, into.fbo); + GL30.glBlitFramebuffer(0, 0, from.viewportWidth, from.viewportHeight, 0, 0, into.viewportWidth, into.viewportHeight, GL30.GL_COLOR_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT | GL30.GL_STENCIL_BUFFER_BIT, GL30.GL_NEAREST); + GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, 0); + GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, 0); + } +} \ No newline at end of file diff --git a/src/main/resources/assets/energonrelics/blockstates/holographic_sky.json b/src/main/resources/assets/energonrelics/blockstates/holographic_sky.json new file mode 100644 index 0000000..26494d5 --- /dev/null +++ b/src/main/resources/assets/energonrelics/blockstates/holographic_sky.json @@ -0,0 +1,10 @@ +{ + "variants": { + "powered=false": { + "model": "energonrelics:block/holographic_sky_off" + }, + "powered=true": { + "model": "energonrelics:block/holographic_sky_on" + } + } +} diff --git a/src/main/resources/assets/energonrelics/lang/en_us.json b/src/main/resources/assets/energonrelics/lang/en_us.json index deb04dc..70e969c 100644 --- a/src/main/resources/assets/energonrelics/lang/en_us.json +++ b/src/main/resources/assets/energonrelics/lang/en_us.json @@ -37,5 +37,6 @@ "block.energonrelics.lightning_rod": "Lightning Rod", "block.energonrelics.forcefield": "Forcefield", "block.energonrelics.forcefield_projector": "Forcefield Projector", - "block.energonrelics.creative_energy_source": "Creative Energy Source" + "block.energonrelics.creative_energy_source": "Creative Energy Source", + "block.energonrelics.holographic_sky": "Holographic Sky" } \ No newline at end of file diff --git a/src/main/resources/assets/energonrelics/models/block/holographic_sky_off.json b/src/main/resources/assets/energonrelics/models/block/holographic_sky_off.json new file mode 100644 index 0000000..bf289ad --- /dev/null +++ b/src/main/resources/assets/energonrelics/models/block/holographic_sky_off.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "energonrelics:block/holographic_sky_off" + } +} diff --git a/src/main/resources/assets/energonrelics/models/block/holographic_sky_on.json b/src/main/resources/assets/energonrelics/models/block/holographic_sky_on.json new file mode 100644 index 0000000..0f6c530 --- /dev/null +++ b/src/main/resources/assets/energonrelics/models/block/holographic_sky_on.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "particle": "energonrelics:block/holographic_sky_off" + } +} diff --git a/src/main/resources/assets/energonrelics/models/item/holographic_sky.json b/src/main/resources/assets/energonrelics/models/item/holographic_sky.json new file mode 100644 index 0000000..cb79fe4 --- /dev/null +++ b/src/main/resources/assets/energonrelics/models/item/holographic_sky.json @@ -0,0 +1,3 @@ +{ + "parent": "energonrelics:block/holographic_sky_off" +} \ No newline at end of file diff --git a/src/main/resources/assets/energonrelics/textures/block/holographic_sky_off.png b/src/main/resources/assets/energonrelics/textures/block/holographic_sky_off.png new file mode 100644 index 0000000..8249a03 Binary files /dev/null and b/src/main/resources/assets/energonrelics/textures/block/holographic_sky_off.png differ diff --git a/src/main/resources/data/energonrelics/loot_tables/blocks/holographic_sky.json b/src/main/resources/data/energonrelics/loot_tables/blocks/holographic_sky.json new file mode 100644 index 0000000..607e29a --- /dev/null +++ b/src/main/resources/data/energonrelics/loot_tables/blocks/holographic_sky.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "energonrelics:holographic_sky" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/energonrelics.mixins.json b/src/main/resources/energonrelics.mixins.json index dfc6126..86bf0bc 100644 --- a/src/main/resources/energonrelics.mixins.json +++ b/src/main/resources/energonrelics.mixins.json @@ -3,15 +3,16 @@ "package": "com.thebrokenrail.energonrelics.mixin", "compatibilityLevel": "JAVA_8", "client": [ - "MixinAbstractFileResourcePack" + "MixinAbstractFileResourcePack", + "MixinWorldRenderer", + "RenderPhaseAccessor" ], "mixins": [ "BrewingRecipeRegistryAccessor", "DamageSourceAccessor", "MixinDefaultBiomeFeatures", "MixinLivingEntity", - "MixinWorld", - "RenderPhaseAccessor" + "MixinWorld" ], "injectors": { "defaultRequire": 1