Skip to content

Commit a530792

Browse files
committed
code cleanup + mod furnace
1 parent d689574 commit a530792

17 files changed

+737
-141
lines changed

src/main/java/io/github/cadiboo/examplemod/ModEventSubscriber.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
import com.google.common.base.Preconditions;
44
import io.github.cadiboo.examplemod.block.HeatCollectorBlock;
55
import io.github.cadiboo.examplemod.block.MiniModelBlock;
6+
import io.github.cadiboo.examplemod.block.ModFurnaceBlock;
67
import io.github.cadiboo.examplemod.config.ConfigHelper;
78
import io.github.cadiboo.examplemod.config.ConfigHolder;
89
import io.github.cadiboo.examplemod.container.HeatCollectorContainer;
10+
import io.github.cadiboo.examplemod.container.ModFurnaceContainer;
911
import io.github.cadiboo.examplemod.init.ModBlocks;
1012
import io.github.cadiboo.examplemod.init.ModItemGroups;
1113
import io.github.cadiboo.examplemod.tileentity.HeatCollectorTileEntity;
1214
import io.github.cadiboo.examplemod.tileentity.MiniModelTileEntity;
15+
import io.github.cadiboo.examplemod.tileentity.ModFurnaceTileEntity;
1316
import net.minecraft.block.Block;
1417
import net.minecraft.block.SoundType;
1518
import net.minecraft.block.material.Material;
@@ -57,7 +60,8 @@ public static void onRegisterBlocks(final RegistryEvent.Register<Block> event) {
5760
// This block has the MISCELLANEOUS material. It is very similar to the Redstone Torch
5861
setup(new MiniModelBlock(Block.Properties.create(Material.MISCELLANEOUS).hardnessAndResistance(1.5F).lightValue(13)), "mini_model"),
5962
// This block has the ROCK material, meaning it needs at least a wooden pickaxe to break it. It is very similar to the Furnace
60-
setup(new HeatCollectorBlock(Block.Properties.create(Material.ROCK).hardnessAndResistance(3.5F).lightValue(13)), "heat_collector")
63+
setup(new HeatCollectorBlock(Block.Properties.create(Material.ROCK).hardnessAndResistance(3.5F).lightValue(13)), "heat_collector"),
64+
setup(new ModFurnaceBlock(Block.Properties.create(Material.ROCK).hardnessAndResistance(3.5F).lightValue(13)), "mod_furnace")
6165
);
6266
LOGGER.debug("Registered Blocks");
6367
}
@@ -113,7 +117,8 @@ public static void onRegisterTileEntityTypes(@Nonnull final RegistryEvent.Regist
113117
event.getRegistry().registerAll(
114118
// We don't have a datafixer for our TileEntity, so we pass null into build
115119
setup(TileEntityType.Builder.create(MiniModelTileEntity::new, ModBlocks.MINI_MODEL).build(null), "mini_model"),
116-
setup(TileEntityType.Builder.create(HeatCollectorTileEntity::new, ModBlocks.HEAT_COLLECTOR).build(null), "heat_collector")
120+
setup(TileEntityType.Builder.create(HeatCollectorTileEntity::new, ModBlocks.HEAT_COLLECTOR).build(null), "heat_collector"),
121+
setup(TileEntityType.Builder.create(ModFurnaceTileEntity::new, ModBlocks.MOD_FURNACE).build(null), "mod_furnace")
117122
);
118123
LOGGER.debug("Registered TileEntityTypes");
119124
}
@@ -126,7 +131,8 @@ public static void onRegisterTileEntityTypes(@Nonnull final RegistryEvent.Regist
126131
public static void onRegisterContainerTypes(@Nonnull final RegistryEvent.Register<ContainerType<?>> event) {
127132
// Register your ContainerTypes here if you have them
128133
event.getRegistry().registerAll(
129-
setup(IForgeContainerType.create(HeatCollectorContainer::new), "heat_collector")
134+
setup(IForgeContainerType.create(HeatCollectorContainer::new), "heat_collector"),
135+
setup(IForgeContainerType.create(ModFurnaceContainer::new), "mod_furnace")
130136
);
131137
LOGGER.debug("Registered ContainerTypes");
132138
}

src/main/java/io/github/cadiboo/examplemod/ModUtil.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
package io.github.cadiboo.examplemod;
22

3+
import net.minecraft.crash.CrashReport;
4+
import net.minecraft.crash.CrashReportCategory;
5+
import net.minecraft.crash.ReportedException;
6+
import net.minecraft.entity.player.PlayerInventory;
7+
import net.minecraft.network.PacketBuffer;
8+
import net.minecraft.tileentity.TileEntity;
9+
import net.minecraft.util.Direction;
10+
import net.minecraft.util.math.BlockPos;
11+
import net.minecraft.world.World;
12+
313
import javax.annotation.Nonnull;
14+
import java.util.Objects;
415

516
/**
617
* Assorted common utility code
@@ -9,6 +20,13 @@
920
*/
1021
public final class ModUtil {
1122

23+
/**
24+
* Cache all the directions instead of calling Direction.values()
25+
* each time (because each call creates a new Direction[] which is wasteful)
26+
* TODO: change to Direction.VALUES once it's ATed
27+
*/
28+
public static final Direction[] DIRECTIONS = Direction.values();
29+
1230
/**
1331
* Returns null, while claiming to never return null.
1432
* Useful for constants with @ObjectHolder who's values are null at compile time, but not at runtime
@@ -22,4 +40,34 @@ public static <T> T _null() {
2240
return null;
2341
}
2442

43+
/**
44+
* Gets the HeatCollectorTileEntity at the position or crashes
45+
*
46+
* @param playerInventory The {@link PlayerInventory} to get the {@link World} from
47+
* @param data The data containing the blockpos
48+
* @param tileEntityClass The class of the TileEntity
49+
* @return The HeatCollectorTileEntity at the position
50+
* @throws ReportedException if the TileEntity at the position is null or not a HeatCollectorTileEntity
51+
*/
52+
public static <T extends TileEntity> T getTileEntityOrCrash(final PlayerInventory playerInventory, final PacketBuffer data, final Class<T> tileEntityClass) {
53+
Objects.requireNonNull(playerInventory, "playerInventory cannot be null!");
54+
Objects.requireNonNull(data, "data cannot be null!");
55+
Objects.requireNonNull(tileEntityClass, "tileEntityClass cannot be null!");
56+
final BlockPos pos = data.readBlockPos();
57+
final World world = playerInventory.player.world;
58+
final TileEntity tileAtPos = world.getTileEntity(pos);
59+
60+
final Throwable error;
61+
if (tileAtPos == null)
62+
error = new NullPointerException("No TileEntity at position");
63+
else if (!tileEntityClass.isAssignableFrom(tileAtPos.getClass()))
64+
error = new ClassCastException(tileAtPos.getClass() + " is not a " + tileEntityClass);
65+
else
66+
return (T) tileAtPos;
67+
CrashReport crashReport = CrashReport.makeCrashReport(error, "Creating Container for a HeatCollectorTileEntity");
68+
CrashReportCategory category = crashReport.makeCategory("Block at position");
69+
CrashReportCategory.addBlockInfo(category, pos, world.getBlockState(pos));
70+
throw new ReportedException(crashReport);
71+
}
72+
2573
}

src/main/java/io/github/cadiboo/examplemod/block/HeatCollectorBlock.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public VoxelShape getShape(final BlockState state, final IBlockReader worldIn, f
6767

6868
/**
6969
* Called on the logical server when a BlockState with a TileEntity is replaced by another BlockState
70+
*
7071
* @deprecated Call via {@link BlockState#onReplaced(World, BlockPos, BlockState, boolean)}
7172
* Implementing/overriding is fine.
7273
*/
@@ -93,7 +94,7 @@ public boolean onBlockActivated(final BlockState state, final World worldIn, fin
9394
if (!worldIn.isRemote) {
9495
final TileEntity tileEntity = worldIn.getTileEntity(pos);
9596
if (tileEntity instanceof HeatCollectorTileEntity) {
96-
NetworkHooks.openGui(((ServerPlayerEntity) player), ((HeatCollectorTileEntity) tileEntity), pos);
97+
NetworkHooks.openGui((ServerPlayerEntity) player, (HeatCollectorTileEntity) tileEntity, pos);
9798
}
9899
}
99100
return true;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package io.github.cadiboo.examplemod.block;
2+
3+
import io.github.cadiboo.examplemod.init.ModTileEntityTypes;
4+
import io.github.cadiboo.examplemod.tileentity.ModFurnaceTileEntity;
5+
import net.minecraft.block.Block;
6+
import net.minecraft.block.BlockState;
7+
import net.minecraft.entity.player.PlayerEntity;
8+
import net.minecraft.entity.player.ServerPlayerEntity;
9+
import net.minecraft.inventory.InventoryHelper;
10+
import net.minecraft.state.BooleanProperty;
11+
import net.minecraft.tileentity.TileEntity;
12+
import net.minecraft.util.Hand;
13+
import net.minecraft.util.math.BlockPos;
14+
import net.minecraft.util.math.BlockRayTraceResult;
15+
import net.minecraft.world.IBlockReader;
16+
import net.minecraft.world.World;
17+
import net.minecraftforge.fml.network.NetworkHooks;
18+
import net.minecraftforge.items.ItemStackHandler;
19+
20+
import javax.annotation.Nullable;
21+
22+
/**
23+
* @author Cadiboo
24+
*/
25+
public class ModFurnaceBlock extends Block {
26+
27+
public static final BooleanProperty BURNING = BooleanProperty.create("burning");
28+
29+
public ModFurnaceBlock(final Properties properties) {
30+
super(properties);
31+
}
32+
33+
@Override
34+
public boolean hasTileEntity(final BlockState state) {
35+
return true;
36+
}
37+
38+
@Nullable
39+
@Override
40+
public TileEntity createTileEntity(final BlockState state, final IBlockReader world) {
41+
// Always use TileEntityType#create to allow registry overrides to work.
42+
return ModTileEntityTypes.MOD_FURNACE.create();
43+
}
44+
45+
/**
46+
* Called on the logical server when a BlockState with a TileEntity is replaced by another BlockState
47+
*
48+
* @deprecated Call via {@link BlockState#onReplaced(World, BlockPos, BlockState, boolean)}
49+
* Implementing/overriding is fine.
50+
*/
51+
@Override
52+
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
53+
if (state.getBlock() != newState.getBlock()) {
54+
TileEntity tileEntity = worldIn.getTileEntity(pos);
55+
if (tileEntity instanceof ModFurnaceTileEntity) {
56+
final ItemStackHandler inventory = ((ModFurnaceTileEntity) tileEntity).inventory;
57+
for (int slot = 0; slot < inventory.getSlots(); ++slot) {
58+
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), inventory.getStackInSlot(slot));
59+
}
60+
}
61+
}
62+
super.onReplaced(state, worldIn, pos, newState, isMoving);
63+
}
64+
65+
/**
66+
* @deprecated Call via {@link BlockState#onBlockActivated(World, PlayerEntity, Hand, BlockRayTraceResult)} whenever possible.
67+
* Implementing/overriding is fine.
68+
*/
69+
@Override
70+
public boolean onBlockActivated(final BlockState state, final World worldIn, final BlockPos pos, final PlayerEntity player, final Hand handIn, final BlockRayTraceResult hit) {
71+
if (!worldIn.isRemote) {
72+
final TileEntity tileEntity = worldIn.getTileEntity(pos);
73+
if (tileEntity instanceof ModFurnaceTileEntity) {
74+
NetworkHooks.openGui((ServerPlayerEntity) player, (ModFurnaceTileEntity) tileEntity, pos);
75+
}
76+
}
77+
return true;
78+
}
79+
80+
}

src/main/java/io/github/cadiboo/examplemod/client/ClientModEventSubscriber.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.github.cadiboo.examplemod.ExampleMod;
44
import io.github.cadiboo.examplemod.client.gui.HeatCollectorScreen;
5+
import io.github.cadiboo.examplemod.client.gui.ModFurnaceScreen;
56
import io.github.cadiboo.examplemod.client.render.tileentity.MiniModelTileEntityRenderer;
67
import io.github.cadiboo.examplemod.init.ModContainerTypes;
78
import io.github.cadiboo.examplemod.tileentity.MiniModelTileEntity;
@@ -42,6 +43,7 @@ public static void onFMLClientSetupEvent(final FMLClientSetupEvent event) {
4243

4344
// Register ContainerType Screens
4445
ScreenManager.registerFactory(ModContainerTypes.HEAT_COLLECTOR, HeatCollectorScreen::new);
46+
ScreenManager.registerFactory(ModContainerTypes.MOD_FURNACE, ModFurnaceScreen::new);
4547
LOGGER.debug("Registered ContainerType Screens");
4648

4749
}

src/main/java/io/github/cadiboo/examplemod/client/gui/HeatCollectorScreen.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ protected void drawGuiContainerForegroundLayer(final int mouseX, final int mouse
5252
@Override
5353
protected void drawGuiContainerBackgroundLayer(final float partialTicks, final int mouseX, final int mouseY) {
5454
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
55-
this.minecraft.getTextureManager().bindTexture(BACKGROUND_TEXTURE);
55+
getMinecraft().getTextureManager().bindTexture(BACKGROUND_TEXTURE);
5656
int startX = this.guiLeft;
5757
int startY = this.guiTop;
5858

@@ -74,7 +74,7 @@ protected void drawGuiContainerBackgroundLayer(final float partialTicks, final i
7474
);
7575
}
7676

77-
if (!tileEntity.inventory.getStackInSlot(0).isEmpty()) // Draw flames
77+
if (!tileEntity.inventory.getStackInSlot(HeatCollectorTileEntity.FUEL_SLOT).isEmpty()) // Draw flames
7878
this.blit(
7979
startX + 81, startY + 58,
8080
176, 0,
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package io.github.cadiboo.examplemod.client.gui;
2+
3+
import com.mojang.blaze3d.platform.GlStateManager;
4+
import io.github.cadiboo.examplemod.container.ModFurnaceContainer;
5+
import io.github.cadiboo.examplemod.tileentity.ModFurnaceTileEntity;
6+
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
7+
import net.minecraft.entity.player.PlayerInventory;
8+
import net.minecraft.util.ResourceLocation;
9+
import net.minecraft.util.text.ITextComponent;
10+
11+
/**
12+
* @author Cadiboo
13+
*/
14+
public class ModFurnaceScreen extends ContainerScreen<ModFurnaceContainer> {
15+
16+
private static final ResourceLocation BACKGROUND_TEXTURE = new ResourceLocation("minecraft", "textures/gui/container/furnace.png");
17+
18+
public ModFurnaceScreen(final ModFurnaceContainer container, final PlayerInventory inventory, final ITextComponent title) {
19+
super(container, inventory, title);
20+
}
21+
22+
@Override
23+
public void render(final int mouseX, final int mouseY, final float partialTicks) {
24+
this.renderBackground();
25+
super.render(mouseX, mouseY, partialTicks);
26+
this.renderHoveredToolTip(mouseX, mouseY);
27+
}
28+
29+
@Override
30+
protected void drawGuiContainerForegroundLayer(final int mouseX, final int mouseY) {
31+
super.drawGuiContainerForegroundLayer(mouseX, mouseY);
32+
// Copied from AbstractFurnaceScreen#drawGuiContainerForegroundLayer
33+
String s = this.title.getFormattedText();
34+
this.font.drawString(s, (float) (this.xSize / 2 - this.font.getStringWidth(s) / 2), 6.0F, 0x404040);
35+
this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8.0F, (float) (this.ySize - 96 + 2), 0x404040);
36+
37+
final ModFurnaceTileEntity tileEntity = this.container.tileEntity;
38+
this.font.drawString(tileEntity.smeltTimeLeft + " / " + tileEntity.maxSmeltTime, 8.0F, this.ySize, 0x404040);
39+
this.font.drawString(tileEntity.fuelBurnTimeLeft + " / " + tileEntity.maxFuelBurnTime, 8.0F, this.ySize + 14, 0x404040);
40+
}
41+
42+
@Override
43+
protected void drawGuiContainerBackgroundLayer(final float partialTicks, final int mouseX, final int mouseY) {
44+
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
45+
getMinecraft().getTextureManager().bindTexture(BACKGROUND_TEXTURE);
46+
int startX = this.guiLeft;
47+
int startY = this.guiTop;
48+
49+
// Screen#blit draws a part of the current texture (assumed to be 256x256) to the screen
50+
// The parameters are (x, y, u, v, width, height)
51+
52+
this.blit(startX, startY, 0, 0, this.xSize, this.ySize);
53+
54+
final ModFurnaceTileEntity tileEntity = container.tileEntity;
55+
if (tileEntity.isBurning()) {
56+
// Draw flames
57+
int flameHeight = getFuelBurnTimeScaled();
58+
this.blit(
59+
startX + 56, startY + 50 - flameHeight,
60+
176, 14 - flameHeight,
61+
14, flameHeight
62+
);
63+
}
64+
if (tileEntity.smeltTimeLeft > 0) {
65+
// Draw progress arrow
66+
int arrowWidth = getSmeltTimeScaled();
67+
this.blit(
68+
startX + 79, startY + 34,
69+
176, 14,
70+
arrowWidth, 14
71+
);
72+
}
73+
}
74+
75+
private int getSmeltTimeScaled() {
76+
final ModFurnaceTileEntity tileEntity = this.container.tileEntity;
77+
final short smeltTimeLeft = tileEntity.smeltTimeLeft;
78+
final short maxSmeltTime = tileEntity.maxSmeltTime;
79+
if (smeltTimeLeft <= 0 || maxSmeltTime <= 0)
80+
return 0;
81+
return (maxSmeltTime - smeltTimeLeft) * 24 / maxSmeltTime; // 24 is the width of the arrow
82+
}
83+
84+
private int getFuelBurnTimeScaled() {
85+
final ModFurnaceTileEntity tileEntity = this.container.tileEntity;
86+
if (tileEntity.maxFuelBurnTime <= 0)
87+
return 0;
88+
return tileEntity.fuelBurnTimeLeft * 14 / tileEntity.maxFuelBurnTime; // 14 is the height of the flames
89+
}
90+
91+
}

src/main/java/io/github/cadiboo/examplemod/client/render/MiniModel.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ public class MiniModel {
2525
public final RegionRenderCacheBuilder regionRenderCacheBuilder;
2626
private final ChunkRender chunkRender;
2727
public ChunkRenderTask generator;
28+
private boolean isBuilt = false;
2829

2930
private MiniModel(final ChunkRender chunkRender, final RegionRenderCacheBuilder regionRenderCacheBuilder) {
3031
this.chunkRender = chunkRender;
3132
this.regionRenderCacheBuilder = regionRenderCacheBuilder;
32-
rebuild();
3333
}
3434

3535
public static MiniModel forTileEntity(final TileEntity tileEntity) {
@@ -70,7 +70,11 @@ public void rebuild() {
7070
for (int ordinal = 0; ordinal < length; ++ordinal) {
7171
buffers.getBuilder(ordinal).setTranslation(0, 0, 0);
7272
}
73+
this.isBuilt = true;
74+
}
7375

76+
public boolean isBuilt() {
77+
return isBuilt;
7478
}
7579

7680
}

src/main/java/io/github/cadiboo/examplemod/client/render/tileentity/MiniModelTileEntityRenderer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public void render(final MiniModelTileEntity tileEntityIn, final double x, final
4141
if (miniModel == null)
4242
return;
4343

44+
if (!miniModel.isBuilt())
45+
miniModel.rebuild();
46+
4447
// Setup correct GL state
4548
this.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
4649
RenderHelper.disableStandardItemLighting();

0 commit comments

Comments
 (0)