<|start_filename|>src/main/java/com/simibubi/create/foundation/render/CreateContexts.java<|end_filename|>
package com.simibubi.create.foundation.render;

import java.util.stream.Stream;

import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.GameStateRegistry;
import com.jozufozu.flywheel.backend.pipeline.InstancingTemplate;
import com.jozufozu.flywheel.backend.pipeline.OneShotTemplate;
import com.jozufozu.flywheel.backend.pipeline.ShaderPipeline;
import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline;
import com.jozufozu.flywheel.backend.source.FileResolution;
import com.jozufozu.flywheel.backend.source.Resolver;
import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.event.GatherContextEvent;
import com.jozufozu.flywheel.util.ResourceUtil;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionProgram;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.resources.ResourceLocation;

@Environment(EnvType.CLIENT)
public class CreateContexts {
	private static final ResourceLocation CONTRAPTION = Create.asResource("context/contraption");

	public static WorldContext<ContraptionProgram> CWORLD;
	public static WorldContext<ContraptionProgram> STRUCTURE;

	public static void flwInit(GatherContextEvent event) {
		Backend backend = event.getBackend();

		GameStateRegistry.register(RainbowDebugStateProvider.INSTANCE);
        FileResolution header = Resolver.INSTANCE.findShader(ResourceUtil.subPath(CONTRAPTION, ".glsl"));

		ShaderPipeline<ContraptionProgram> instancing = new WorldShaderPipeline<>(ContraptionProgram::new, InstancingTemplate.INSTANCE, header);
		ShaderPipeline<ContraptionProgram> structure = new WorldShaderPipeline<>(ContraptionProgram::new, OneShotTemplate.INSTANCE, header);

		CWORLD = backend.register(WorldContext.builder(backend, CONTRAPTION)
				.build(instancing));

		STRUCTURE = backend.register(WorldContext.builder(backend, CONTRAPTION)
				.setSpecStream(() -> Stream.of(AllProgramSpecs.STRUCTURE))
				.build(structure));
	}

}


<|start_filename|>src/main/java/com/simibubi/create/lib/condition/ModLoadedCondition.java<|end_filename|>
package com.simibubi.create.lib.condition;

import com.simibubi.create.lib.data.ICondition;

import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.resources.ResourceLocation;

public class ModLoadedCondition implements ICondition {
	private static final ResourceLocation NAME = new ResourceLocation("create", "mod_loaded");
	private final String modid;
	private final boolean loaded;

	public ModLoadedCondition(String modid) {
		this.modid = modid;
		this.loaded = FabricLoader.getInstance().isModLoaded(modid);
	}

	@Override
	public String toString() {
		return "mod_loaded(\"" + modid + "\")";
	}

	@Override
	public ResourceLocation getID() {
		return NAME;
	}

	@Override
	public boolean test() {
		return loaded;
	}
}


<|start_filename|>src/main/java/com/simibubi/create/lib/condition/NotCondition.java<|end_filename|>
package com.simibubi.create.lib.condition;

import com.simibubi.create.lib.data.ICondition;

import net.minecraft.resources.ResourceLocation;

public class NotCondition implements ICondition
{
	private static final ResourceLocation NAME = new ResourceLocation("forge", "not");
	private final ICondition child;

	public NotCondition(ICondition child) {
		this.child = child;
	}

	@Override
	public String toString() {
		return "!" + child;
	}

	@Override
	public ResourceLocation getID() {
		return NAME;
	}

	@Override
	public boolean test() {
		return !child.test();
	}
}


<|start_filename|>src/main/java/com/simibubi/create/lib/util/FluidTileDataHandler.java<|end_filename|>
package com.simibubi.create.lib.util;

import java.util.HashMap;
import java.util.Map;

import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
import com.simibubi.create.lib.transfer.TransferUtil;
import com.simibubi.create.lib.transfer.fluid.FluidStack;
import com.simibubi.create.lib.transfer.fluid.FluidTransferable;
import com.simibubi.create.lib.transfer.fluid.IFluidHandler;

import com.simibubi.create.lib.util.FluidHandlerData.FluidTankData;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.material.Fluid;

public class FluidTileDataHandler {
	public static final ResourceLocation PACKET_ID = Create.asResource("fluid_tile_handler_data");

	@Environment(EnvType.CLIENT)
	private static final Map<BlockPos, FluidTankData[]> CACHED_DATA = new HashMap<>();

	public static void sendDataToClients(ServerLevel world, FluidTransferable transferable) {
		world.getPlayers(player -> {
			IFluidHandler handler = TransferUtil.getFluidHandler((BlockEntity) transferable).orElse(null);
			FluidTankData[] tankData = new FluidTankData[handler.getTanks()];
			for (int i = 0; i < tankData.length; i++) {
				FluidStack stack = handler.getFluidInTank(i);
				String translationKey = stack.getTranslationKey();
				long amount = stack.getAmount();
				long capacity = handler.getTankCapacity(i);
				tankData[i] = new FluidTankData(translationKey, amount, capacity, stack.getFluid());
			}
			ServerPlayNetworking.send(player, PACKET_ID, createPacket(tankData, (BlockEntity) transferable));
			return true;
		});
	}

	public static FriendlyByteBuf createPacket(FluidTankData[] data, BlockEntity be) {
		FriendlyByteBuf buf = PacketByteBufs.create();
		buf.writeInt(data.length);
		for (FluidTankData tank : data) {
			buf.writeUtf(tank.translationKey());
			buf.writeLong(tank.amount());
			buf.writeLong(tank.capacity());
			buf.writeResourceLocation(Registry.FLUID.getKey(tank.fluid()));
		}
		buf.writeBlockPos(be.getBlockPos());
		return buf;
	}

	public static FluidTankData[] readPacket(FriendlyByteBuf buf) {
		FluidTankData[] data = new FluidTankData[buf.readInt()];
		for (int i = 0; i < data.length; i++) {
			String translationKey = buf.readUtf();
			long amount = buf.readLong();
			long capacity = buf.readLong();
			Fluid fluid = Registry.FLUID.get(buf.readResourceLocation());
			data[i] = new FluidTankData(translationKey, amount, capacity, fluid);
		}
		return data;
	}

	public static IFluidHandler getCachedHandler(BlockEntity be) {
		FluidTankData[] data = CACHED_DATA.get(be.getBlockPos());
		if(data == null) {
			if (be instanceof FluidTankTileEntity tank) {
				data = CACHED_DATA.get(tank.getController());
			}
			if (data == null) return null;
		}
		FluidTankData[] finalData = data;
		return new IFluidHandler() {
			@Override
			public int getTanks() {
				return finalData.length;
			}

			@Override
			public FluidStack getFluidInTank(int tank) {
				return new FluidStack(finalData[tank].fluid(), finalData[tank].amount());
			}

			@Override
			public long getTankCapacity(int tank) {
				return finalData[tank].capacity();
			}

			@Override
			public long fill(FluidStack stack, boolean sim) {
				return 0;
			}

			@Override
			public FluidStack drain(FluidStack stack, boolean sim) {
				return null;
			}

			@Override
			public FluidStack drain(long amount, boolean sim) {
				return null;
			}
		};
	}

	@Environment(EnvType.CLIENT)
	public static void initClient() {
		ClientPlayNetworking.registerGlobalReceiver(PACKET_ID, (client, handler, buf, sender) -> {
			FluidTankData[] data = readPacket(buf);
			BlockPos pos = buf.readBlockPos();
			client.execute(() -> CACHED_DATA.put(pos, data));
		});
	}

	public static record FluidTankData(String translationKey, long amount, long capacity, Fluid fluid) {
	}
}


<|start_filename|>src/main/java/com/simibubi/create/lib/util/FluidUtil.java<|end_filename|>
package com.simibubi.create.lib.util;

import net.minecraft.world.level.material.Fluid;

public class FluidUtil {
	public static int getLuminosity(Fluid fluid) {
		return fluid.defaultFluidState().createLegacyBlock().getLightEmission();
	}
}


<|start_filename|>src/main/java/com/simibubi/create/lib/mixin/client/ItemRendererMixin.java<|end_filename|>
package com.simibubi.create.lib.mixin.client;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.lib.render.TransformTypeDependentItemBakedModel;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.world.item.ItemStack;

@Environment(EnvType.CLIENT)
@Mixin(value = ItemRenderer.class, priority = 10000)
public abstract class ItemRendererMixin {
	@ModifyVariable(method = "render", at = @At("HEAD"), argsOnly = true)
	private BakedModel create$handleModel(BakedModel model, ItemStack itemStack, ItemTransforms.TransformType transformType, boolean leftHand, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model1) {
		if (model instanceof TransformTypeDependentItemBakedModel handler) {
			return handler.create$handlePerspective(transformType);
		}
		return model;
	}
}


<|start_filename|>src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java<|end_filename|>
package com.simibubi.create.foundation.render;

import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.event.GatherContextEvent;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.flwdata.BeltData;
import com.simibubi.create.content.contraptions.base.flwdata.BeltType;
import com.simibubi.create.content.contraptions.base.flwdata.RotatingData;
import com.simibubi.create.content.contraptions.base.flwdata.RotatingType;
import com.simibubi.create.content.contraptions.components.actors.flwdata.ActorData;
import com.simibubi.create.content.contraptions.components.actors.flwdata.ActorType;
import com.simibubi.create.content.logistics.block.flap.FlapData;
import com.simibubi.create.content.logistics.block.flap.FlapType;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.resources.ResourceLocation;

@Environment(EnvType.CLIENT)
public class AllMaterialSpecs {
	public static void init() {
		// noop, make sure the static field are loaded.
	}

	public static final StructType<RotatingData> ROTATING = new RotatingType();
	public static final StructType<BeltData> BELTS = new BeltType();
	public static final StructType<ActorData> ACTORS = new ActorType();
	public static final StructType<FlapData> FLAPS = new FlapType();

	public static void flwInit(GatherContextEvent event) {
		event.getBackend().register(Locations.ROTATING, ROTATING);
		event.getBackend().register(Locations.BELTS, BELTS);
		event.getBackend().register(Locations.ACTORS, ACTORS);
		event.getBackend().register(Locations.FLAPS, FLAPS);
	}

	public static class Locations {
		public static final ResourceLocation ROTATING = Create.asResource("rotating");
		public static final ResourceLocation BELTS = Create.asResource("belts");
		public static final ResourceLocation ACTORS = Create.asResource("actors");
		public static final ResourceLocation FLAPS = Create.asResource("flaps");
	}
}


<|start_filename|>src/main/java/com/simibubi/create/lib/condition/TagEmptyCondition.java<|end_filename|>
package com.simibubi.create.lib.condition;

import com.simibubi.create.lib.data.ICondition;

import net.minecraft.resources.ResourceLocation;

public class TagEmptyCondition implements ICondition {
	private final ResourceLocation tag_name;

	public TagEmptyCondition(String location)
	{
		this(new ResourceLocation(location));
	}

	public TagEmptyCondition(String namespace, String path)
	{
		this(new ResourceLocation(namespace, path));
	}

	public TagEmptyCondition(ResourceLocation tag)
	{
		this.tag_name = tag;
	}

	@Override
	public ResourceLocation getID() {
		return new ResourceLocation("create", "tag_empty");
	}

	@Override
	public boolean test() {
		return false;
	}
}
