Worldgen, Compass (temp)

This commit is contained in:
Sebastian Hartte
2020-07-07 01:55:15 +02:00
parent 9220ca0048
commit 5eece068ba
42 changed files with 359 additions and 1665 deletions
+12 -1
View File
@@ -6,8 +6,10 @@ import appeng.bootstrap.components.IClientSetupComponent;
import appeng.bootstrap.components.IItemColorRegistrationComponent;
import appeng.bootstrap.components.IModelBakeComponent;
import appeng.client.gui.implementations.*;
import appeng.client.render.SimpleModelLoader;
import appeng.client.render.cablebus.CableBusModelLoader;
import appeng.client.render.effects.*;
import appeng.client.render.model.SkyCompassModel;
import appeng.client.render.tesr.InscriberTESR;
import appeng.client.render.tesr.SkyChestTESR;
import appeng.container.implementations.*;
@@ -36,6 +38,7 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.render.entity.ItemEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
@@ -46,6 +49,7 @@ import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -234,7 +238,8 @@ public final class AppEngClient extends AppEngBase {
ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> new CableBusModelLoader((PartModels) Api.INSTANCE.registries().partModels()));
// FIXME FABRIC addBuiltInModel("glass", GlassModel::new);
// FIXME FABRIC addBuiltInModel("sky_compass", SkyCompassModel::new);
addBuiltInModel("block/sky_compass", SkyCompassModel::new);
addBuiltInModel("item/sky_compass", SkyCompassModel::new);
// FIXME FABRIC addBuiltInModel("dummy_fluid_item", DummyFluidItemModel::new);
// FIXME FABRIC addBuiltInModel("memory_card", MemoryCardModel::new);
// FIXME FABRIC addBuiltInModel("biometric_card", BiometricCardModel::new);
@@ -256,6 +261,12 @@ public final class AppEngClient extends AppEngBase {
// FIXME FABRIC new CableBusModelLoader());
}
private static <T extends UnbakedModel> void addBuiltInModel(String id, Supplier<T> modelFactory) {
ModelLoadingRegistry.INSTANCE.registerResourceProvider(
resourceManager -> new SimpleModelLoader<T>(AppEng.makeId(id), modelFactory)
);
}
private void registerScreens() {
ScreenRegistry.register(GrinderContainer.TYPE, GrinderScreen::new);
ScreenRegistry.register(QNBContainer.TYPE, QNBScreen::new);
@@ -0,0 +1,26 @@
package appeng.client.render;
import appeng.client.render.model.AutoRotatingBakedModel;
import net.minecraft.client.render.model.BakedModel;
public final class BakedModelUnwrapper {
private BakedModelUnwrapper() {
}
public static <T> T unwrap(BakedModel model, Class<T> targetClass) {
if (targetClass.isInstance(model)) {
return targetClass.cast(model);
}
if (model instanceof AutoRotatingBakedModel) {
model = ((AutoRotatingBakedModel) model).getWrapped();
if (targetClass.isInstance(model)) {
return targetClass.cast(model);
}
}
return null;
}
}
@@ -0,0 +1,34 @@
package appeng.client.render;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* An unbaked model that has standard models as a dependency and produces a custom baked model
* as a result.
*/
public interface BasicUnbakedModel extends UnbakedModel {
default Stream<SpriteIdentifier> getAdditionalTextures() {
return Stream.empty();
}
@Override
default Collection<SpriteIdentifier> getTextureDependencies(Function<Identifier, UnbakedModel> unbakedModelGetter, Set<Pair<String, String>> unresolvedTextureReferences) {
return Stream.concat(
getModelDependencies().stream()
.map(unbakedModelGetter)
.flatMap(ubm -> ubm.getTextureDependencies(unbakedModelGetter, unresolvedTextureReferences).stream()),
getAdditionalTextures()
).collect(Collectors.toList());
}
}
@@ -0,0 +1,33 @@
package appeng.client.render;
import net.fabricmc.fabric.api.client.model.ModelProviderContext;
import net.fabricmc.fabric.api.client.model.ModelResourceProvider;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.util.Identifier;
import java.util.function.Supplier;
/**
* A quaint model provider that provides a single model with a single given resource identifier.
*/
public class SimpleModelLoader<T extends UnbakedModel> implements ModelResourceProvider {
private final Identifier identifier;
private final Supplier<T> factory;
public SimpleModelLoader(Identifier identifier, Supplier<T> factory) {
this.factory = factory;
this.identifier = identifier;
}
@Override
public UnbakedModel loadModelResource(Identifier identifier, ModelProviderContext modelProviderContext) {
if (identifier.equals(this.identifier)) {
return factory.get();
} else {
return null;
}
}
}
@@ -19,16 +19,15 @@
package appeng.client.render.cablebus;
import appeng.api.util.AEColor;
import appeng.client.render.BasicUnbakedModel;
import appeng.core.AELog;
import appeng.core.features.registries.PartModels;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
@@ -36,16 +35,14 @@ import net.minecraft.util.Identifier;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* The built-in model for the cable bus block.
*/
@Environment(EnvType.CLIENT)
public class CableBusModel implements UnbakedModel {
public class CableBusModel implements BasicUnbakedModel {
private final PartModels partModels;
@@ -59,6 +56,11 @@ public class CableBusModel implements UnbakedModel {
return partModels.getModels();
}
@Override
public Stream<SpriteIdentifier> getAdditionalTextures() {
return CableBuilder.getTextures().stream();
}
@Nullable
@Override
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
@@ -75,15 +77,6 @@ public class CableBusModel implements UnbakedModel {
return new CableBusBakedModel(cableBuilder, facadeBuilder, partModels, particleTexture);
}
@Override
public Collection<SpriteIdentifier> getTextureDependencies(Function<Identifier, UnbakedModel> unbakedModelGetter, Set<Pair<String, String>> unresolvedTextureReferences) {
return Stream.concat(
getModelDependencies().stream()
.map(unbakedModelGetter)
.flatMap(ubm -> ubm.getTextureDependencies(unbakedModelGetter, unresolvedTextureReferences).stream()),
CableBuilder.getTextures().stream()
).collect(Collectors.toList());
}
private Map<Identifier, BakedModel> loadPartModels(ModelLoader loader,
ModelBakeSettings rotationContainer) {
@@ -28,6 +28,10 @@ public class AutoRotatingBakedModel extends ForwardingBakedModel implements Fabr
return false;
}
public BakedModel getWrapped() {
return wrapped;
}
@Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
RenderContext.QuadTransform transform = getTransform(blockView, pos);
@@ -0,0 +1,229 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import appeng.hooks.CompassManager;
import appeng.hooks.CompassResult;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Quaternion;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* This baked model combines the quads of a compass base and the quads of a
* compass pointer, which will be rotated around the Y-axis to get the compass
* to point in the right direction.
*/
public class SkyCompassBakedModel implements BakedModel, FabricBakedModel {
// Rotation is expressed as radians
private final BakedModel base;
private final BakedModel pointer;
private float fallbackRotation = 0;
public SkyCompassBakedModel(BakedModel base, BakedModel pointer) {
this.base = base;
this.pointer = pointer;
}
public BakedModel getBase() {
return base;
}
public BakedModel getPointer() {
return pointer;
}
@Override
public boolean isVanillaAdapter() {
return false;
}
@Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
MeshBuilder mb = RendererAccess.INSTANCE.getRenderer().meshBuilder();
mb.getEmitter().square(Direction.UP, 0, 0, 1, 1, 0).emit();
Mesh build = mb.build();
context.meshConsumer().accept(build);
float rotation = getAnimatedRotation(pos, false);
emitQuads(context, rotation);
}
@Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
// This is used to render a compass pointing in a specific direction when being
// held in hand
emitQuads(context, this.fallbackRotation);
}
private void emitQuads(RenderContext context, float rotation) {
// Pre-compute the quad count to avoid list resizes
context.fallbackConsumer().accept(this.base);
// Set up the rotation around the Y-axis for the pointer
context.pushTransform(quad -> {
Quaternion quaternion = new Quaternion(0, rotation, 0, false);
Vector3f pos = new Vector3f();
for (int i = 0; i < 4; i++) {
quad.copyPos(i, pos);
pos.add(-0.5f, -0.5f, -0.5f);
pos.rotate(quaternion);
pos.add(0.5f, 0.5f, 0.5f);
quad.pos(i, pos);
}
return true;
});
context.fallbackConsumer().accept(this.pointer);
context.popTransform();
}
// this is used in the block entity renderer
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
return base.getQuads(state, face, random);
}
@Override
public boolean useAmbientOcclusion() {
return this.base.useAmbientOcclusion();
}
@Override
public boolean hasDepth() {
return true;
}
@Override
public boolean isSideLit() {
return false;
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public Sprite getSprite() {
return this.base.getSprite();
}
@Override
public ModelTransformation getTransformation() {
return this.base.getTransformation();
}
@Override
public ModelOverrideList getOverrides() {
/*
* This handles setting the rotation of the compass when being held in hand. If
* it's not held in hand, it'll animate using the spinning animation.
*/
return new ModelOverrideList(null, null, null, Collections.emptyList()) {
@Override
public BakedModel apply(BakedModel originalModel, ItemStack stack, @Nullable ClientWorld world,
@Nullable LivingEntity entity) {
// FIXME: This check prevents compasses being held by OTHERS from getting the
// rotation, BUT do we actually still need this???
if (world != null && entity instanceof ClientPlayerEntity) {
PlayerEntity player = (PlayerEntity) entity;
float offRads = (float) (player.yaw / 180.0f * (float) Math.PI + Math.PI);
SkyCompassBakedModel.this.fallbackRotation = offRads
+ getAnimatedRotation(player.getBlockPos(), true);
} else {
SkyCompassBakedModel.this.fallbackRotation = getAnimatedRotation(null, false);
}
return originalModel;
}
};
}
/**
* Gets the effective, animated rotation for the compass given the current
* position of the compass.
*/
public static float getAnimatedRotation(@Nullable BlockPos pos, boolean prefetch) {
// Only query for a meteor position if we know our own position
if (pos != null) {
CompassResult cr = CompassManager.INSTANCE.getCompassDirection(0, pos.getX(), pos.getY(), pos.getZ());
// Prefetch meteor positions from the server for adjacent blocks so they are
// available more quickly when
// we're moving
if (prefetch) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
CompassManager.INSTANCE.getCompassDirection(0, pos.getX() + i - 1, pos.getY(),
pos.getZ() + j - 1);
}
}
}
if (cr.isValidResult()) {
if (cr.isSpin()) {
long timeMillis = System.currentTimeMillis();
// .5 seconds per full rotation
timeMillis %= 500;
return timeMillis / 500.f * (float) Math.PI * 2;
} else {
return (float) cr.getRad();
}
}
}
long timeMillis = System.currentTimeMillis();
// 3 seconds per full rotation
timeMillis %= 3000;
return timeMillis / 3000.f * (float) Math.PI * 2;
}
}
@@ -0,0 +1,67 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import appeng.client.render.BasicUnbakedModel;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
/**
* The parent model for the compass baked model. Declares the dependencies for
* the base and pointer submodels mostly.
*/
public class SkyCompassModel implements BasicUnbakedModel {
private static final Identifier MODEL_BASE = new Identifier(
"appliedenergistics2:block/sky_compass_base");
private static final Identifier MODEL_POINTER = new Identifier(
"appliedenergistics2:block/sky_compass_pointer");
public static final List<Identifier> DEPENDENCIES = ImmutableList.of(MODEL_BASE, MODEL_POINTER);
@Nullable
@Override
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
BakedModel baseModel = loader.bake(MODEL_BASE, rotationContainer);
BakedModel pointerModel = loader.bake(MODEL_POINTER, rotationContainer);
return new SkyCompassBakedModel(baseModel, pointerModel);
}
@Override
public Collection<Identifier> getModelDependencies() {
return ImmutableSet.of(MODEL_BASE, MODEL_POINTER);
}
}
@@ -18,23 +18,29 @@
package appeng.client.render.tesr;
import appeng.client.render.BakedModelUnwrapper;
import appeng.client.render.FacingToRotation;
import appeng.client.render.model.SkyCompassBakedModel;
import appeng.tile.misc.SkyCompassBlockEntity;
import net.fabricmc.api.EnvType;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.TexturedRenderLayers;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.BlockModelRenderer;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.Direction;
import net.fabricmc.api.Environment;
import net.minecraft.util.math.Quaternion;
import appeng.client.render.FacingToRotation;
import appeng.tile.misc.SkyCompassBlockEntity;
import java.util.Random;
@Environment(EnvType.CLIENT)
public class SkyCompassTESR extends BlockEntityRenderer<SkyCompassBlockEntity> {
@@ -48,18 +54,22 @@ public class SkyCompassTESR extends BlockEntityRenderer<SkyCompassBlockEntity> {
@Override
public void render(SkyCompassBlockEntity te, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
int combinedLightIn, int combinedOverlayIn) {
if (blockRenderer == null) {
blockRenderer = MinecraftClient.getInstance().getBlockRenderManager();
}
VertexConsumer buffer = buffers.getBuffer(TexturedRenderLayers.getEntityTranslucentCull());
BlockModelRenderer modelRenderer = blockRenderer.getModelRenderer();
BlockState blockState = te.getCachedState();
BakedModel model = blockRenderer.getModels().getModel(blockState);
SkyCompassBakedModel skyCompassModel = BakedModelUnwrapper.unwrap(model, SkyCompassBakedModel.class);
if (skyCompassModel == null) {
return;
}
BakedModel baseModel = skyCompassModel.getBase();
BakedModel pointerModel = skyCompassModel.getPointer();
// FIXME: Rotation was previously handled by an auto rotating model I think, but
// FIXME: Should be handled using matrices instead
Direction forward = te.getForward();
Direction up = te.getUp();
// This ensures the needle isn't flipped by the model rotator. Since the model
@@ -71,14 +81,19 @@ public class SkyCompassTESR extends BlockEntityRenderer<SkyCompassBlockEntity> {
// Flip forward/up for rendering, the base model is facing up without any
// rotation
ms.push();
VertexConsumer buffer = buffers.getBuffer(RenderLayer.getSolid());
modelRenderer.render(te.getWorld(), model, blockState, te.getPos(), ms, buffer, false, new Random(), 42L, combinedOverlayIn);
// modelRenderer.render(ms.peek(), buffer, null, baseModel, 1, 1, 1, combinedLightIn, combinedOverlayIn);
float rotation = getRotation(te);
ms.translate(0.5D, 0.5D, 0.5D);
FacingToRotation.get(up, forward).push(ms);
ms.multiply(new Quaternion(0, rotation, 0, false));
ms.translate(-0.5D, -0.5D, -0.5D);
// FIXME FABRIC ModelDataMap modelData = new ModelDataMap.Builder().withInitial(SkyCompassBakedModel.ROTATION, getRotation(te)).build();
blockRenderer.getModelRenderer().render(ms.peek(), buffer, null, model, 1, 1, 1, combinedLightIn,
combinedOverlayIn);
modelRenderer.render(ms.peek(), buffer, null, pointerModel, 1, 1, 1, combinedLightIn, combinedOverlayIn);
ms.pop();
}
@@ -88,13 +103,13 @@ public class SkyCompassTESR extends BlockEntityRenderer<SkyCompassBlockEntity> {
float rotation = 0;
if (skyCompass.getForward() == Direction.UP || skyCompass.getForward() == Direction.DOWN) {
// FIXME FABRIC rotation = SkyCompassBakedModel.getAnimatedRotation(skyCompass.getPos(), false);
rotation = SkyCompassBakedModel.getAnimatedRotation(skyCompass.getPos(), false);
} else {
// FIXME FABRIC rotation = SkyCompassBakedModel.getAnimatedRotation(null, false);
rotation = SkyCompassBakedModel.getAnimatedRotation(null, false);
}
if (skyCompass.getForward() == Direction.DOWN) {
// FIXME FABRIC rotation = flipidiy(rotation);
rotation = flipidiy(rotation);
}
return rotation;