From 4273579b17c737623897f0dd376f00268ff5eb58 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Thu, 23 Dec 2021 13:17:25 -0800 Subject: [PATCH] Getting started --- Your-First-Instance.md | 127 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 Your-First-Instance.md diff --git a/Your-First-Instance.md b/Your-First-Instance.md new file mode 100644 index 0000000..444a698 --- /dev/null +++ b/Your-First-Instance.md @@ -0,0 +1,127 @@ +This wiki is a work in progress! Hopefully it can lead you in the right direction. + +Start by creating an empty subclass of `TileEntityInstance`, and build it up from there. +```java +public class MyBlockInstance extends TileEntityInstance { + + public MyBlockInstance(MaterialManager materialManager, MyBlockEntity tile) { + super(materialManager, tile); + } + + @Override + public void remove() { + // You'll be doing some cleanup here later. + } +} +``` +And you have to register the `Instance` with Flywheel, so might as well get that out of the way now. +```java +public class MyInstances { + public static void init() { + InstancedRenderRegistry r = InstancedRenderRegistry.getInstance(); + + r.tile(MyBlockEntityTypes.MY_BLOCK_ENTITY) + .setSkipRender(true) // Completely skip the BlockEntityRenderer. + .factory(MyBlockInstance::new); // Use our TileEntityInstance instead. + } +} +``` +And be sure to call `MyInstances.init()` somewhere! + +But, let's get back to the fun stuff. As it currently stands, our Instance does nothing but sit there and take up +memory. So, you might ask, how can I get it to render something? + +In Flywheel, `TileEntityInstance`s don't *technically* render models on their own. Instead, they ask the +`MaterialManager` to create a parameterized *instance* of a model. The `TileEntityInstance` is then free to change the +parameters, and Flywheel takes care of the rest, ensuring that your copy of the model is rendered in the right place, +with the right light, etc. + +So let's have your Instance ask the MaterialManager for a copy of some bricks, because why not? +```java +public class MyBlockInstance extends TileEntityInstance { + private final ModelData model; + + public MyBlockInstance(MaterialManager materialManager, MyBlockEntity tile) { + super(materialManager, tile); + + model = materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(Blocks.BRICKS.defaultBlockState()) // Feel free to use a different blockstate! + .createInstance(); + + // translate the model to make it appear at your BlockEntity + model.loadIdentity() + .translate(getInstancePosition()); + } + + ... +} +``` + +And now that you've acquired resources, you have to make sure to clean up after yourself! +```java +public class MyBlockInstance extends TileEntityInstance { + ... + + @Override + public void remove() { + model.delete(); + } +} +``` +If you don't call `InstanceData#delete()`, all the models you ask for will be left behind when +your block entity is broken. + +If you were to launch your game and place down your tile entity now, you'd see bricks, but they'd be very dark! + +That's because you never tell Flywheel how to light the bricks! + +In Flywheel, there's no need to query block and sky light every frame (like what's done for BlockEntityRenderers). +Instead, light data can be stored in the `ModelData`, and updated as necessary. Flywheel already does most of the +heavy lifting here, it's just on you to make sure you update your parameters when Flywheel detects a light update. +You do this by overriding (drum roll...) `#updateLight`. + +```java +public class MyBlockInstance extends TileEntityInstance { + ... + + @Override + public void updateLight() { + relight(getWorldPosition(), model); + } +} +``` +`relight(...)` is a helper method that takes a BlockPos and a series of model parameters, and updates the parameters +with the light data at the given position. + +And so now your class looks like this: +```java +import com.jozufozu.flywheel.core.materials.model.ModelData; + +public class MyBlockInstance extends TileEntityInstance { + + private final ModelData model; + + public MyBlockInstance(MaterialManager materialManager, MyBlockEntity tile) { + super(materialManager, tile); + + model = materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(Blocks.BRICKS.defaultBlockState()) + .createInstance(); + + model.loadIdentity() + .translate(getInstancePosition()); + } + + @Override + public void remove() { + model.delete(); + } + + @Override + public void updateLight() { + relight(getWorldPosition(), model); + } +} +``` \ No newline at end of file