1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00

Update to latest Forge

- Lots of refactoring/cleanup to Forge's events and client APIs.
   - Render types/layers for blocks are now set on the model rather than
     in code.

   - Models now can work with multiple render types. As this would
     massively complicate the implementation of the turtle item model, we
     now implement a much simpler version, which makes use of Forge's
     BakedModel.getRenderPasses to return a separate model for the core
     turtle and each upgrade.

 - Send monitor contents to players immediately when they start watching
   the chunk. ChunkWatchEvent.Watch is now fired from a more sensible
   location, so this is much easier to implement!
This commit is contained in:
Jonathan Coates 2022-07-16 19:08:11 +01:00
parent e906f3ebc3
commit 4a273ae8e5
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
37 changed files with 204 additions and 393 deletions

View File

@ -109,8 +109,8 @@
}
}
// mappings channel: 'parchment', version: "${mapping_version}-${mc_version}"
mappings channel: 'official', version: mc_version
mappings channel: 'parchment', version: "${mapping_version}-${mc_version}"
// mappings channel: 'official', version: mc_version
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
@ -149,9 +149,9 @@ accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-forge-api:11.0.0.206")
extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-common-api:11.0.0.206")
extraModsRuntimeOnly fg.deobf("mezz.jei:jei-1.19-forge:11.0.0.206")
extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-forge-api:11.0.0.211")
extraModsCompileOnly fg.deobf("mezz.jei:jei-1.19-common-api:11.0.0.211")
extraModsRuntimeOnly fg.deobf("mezz.jei:jei-1.19-forge:11.0.0.211")
shade 'org.squiddev:Cobalt:0.5.5'
shade 'io.netty:netty-codec-http:4.1.76.Final'

View File

@ -6,6 +6,6 @@ mod_version=1.100.8
# Minecraft properties (update mods.toml when changing)
mc_version=1.19
mapping_version=2022.03.13
forge_version=41.0.38
mapping_version=1.18.2-2022.07.03
forge_version=41.0.98
# NO SERIOUSLY, UPDATE mods.toml WHEN CHANGING

View File

@ -7,7 +7,7 @@
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
import net.minecraftforge.data.event.GatherDataEvent;
import javax.annotation.Nonnull;
import java.util.function.Consumer;

View File

@ -47,6 +47,7 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
/**
* The associated registry.
*
* @return The registry for pocket upgrade serialisers.
* @see #REGISTRY_ID
*/

View File

@ -14,7 +14,7 @@
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.level.BlockEvent;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

View File

@ -14,7 +14,7 @@
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.Nonnull;
@ -140,7 +140,10 @@ public void add( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> add )
add.accept( new Upgrade<>( id, serialiser, s -> {
s.addProperty( "item", ForgeRegistries.ITEMS.getKey( toolItem ).toString() );
if( adjective != null ) s.addProperty( "adjective", adjective );
if( craftingItem != null ) s.addProperty( "craftItem", ForgeRegistries.ITEMS.getKey( craftingItem ).toString() );
if( craftingItem != null )
{
s.addProperty( "craftItem", ForgeRegistries.ITEMS.getKey( craftingItem ).toString() );
}
if( damageMultiplier != null ) s.addProperty( "damageMultiplier", damageMultiplier );
if( breakable != null ) s.addProperty( "breakable", breakable.location().toString() );
} ) );

View File

@ -67,12 +67,14 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
*
* This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and
* {@link RegistryManager#getRegistry(ResourceKey)}.
*
* @see #registry()
*/
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_upgrade_serialiser" ) );
/**
* The associated registry.
*
* @return The registry for pocket upgrade serialisers.
* @see #REGISTRY_ID
*/

View File

@ -68,7 +68,7 @@ public interface IUpgradeBase
* @param stack The stack to check. This is guaranteed to be non-empty and have the same item as
* {@link #getCraftingItem()}.
* @return If this stack may be used to equip this upgrade.
* @see net.minecraftforge.common.crafting.NBTIngredient#test(ItemStack) For the implementation of the default
* @see net.minecraftforge.common.crafting.StrictNBTIngredient#test(ItemStack) For the implementation of the default
* check.
*/
default boolean isItemSuitable( @Nonnull ItemStack stack )

View File

@ -10,7 +10,7 @@
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ClientPlayerNetworkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@ -18,9 +18,9 @@
public class ClientHooks
{
@SubscribeEvent
public static void onWorldUnload( WorldEvent.Unload event )
public static void onWorldUnload( LevelEvent.Unload event )
{
if( event.getWorld().isClientSide() )
if( event.getLevel().isClientSide() )
{
ClientMonitor.destroyAll();
SpeakerManager.reset();
@ -28,13 +28,13 @@ public static void onWorldUnload( WorldEvent.Unload event )
}
@SubscribeEvent
public static void onLogIn( ClientPlayerNetworkEvent.LoggedInEvent event )
public static void onLogIn( ClientPlayerNetworkEvent.LoggingIn event )
{
ComputerCraft.clientComputerRegistry.reset();
}
@SubscribeEvent
public static void onLogOut( ClientPlayerNetworkEvent.LoggedOutEvent event )
public static void onLogOut( ClientPlayerNetworkEvent.LoggingOut event )
{
ComputerCraft.clientComputerRegistry.reset();
}

View File

@ -19,8 +19,6 @@
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.client.renderer.item.ItemPropertyFunction;
@ -28,10 +26,8 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ForgeModelBakery;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
@ -69,17 +65,22 @@ public final class ClientRegistry
private ClientRegistry() {}
@SubscribeEvent
public static void registerModels( ModelRegistryEvent event )
public static void registerModelLoaders( ModelEvent.RegisterGeometryLoaders event )
{
event.register( "turtle", TurtleModelLoader.INSTANCE );
}
@SubscribeEvent
public static void registerModels( ModelEvent.RegisterAdditional event )
{
ModelLoaderRegistry.registerLoader( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ), TurtleModelLoader.INSTANCE );
for( String model : EXTRA_MODELS )
{
ForgeModelBakery.addSpecialModel( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ) );
event.register( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ) );
}
}
@SubscribeEvent
public static void onItemColours( ColorHandlerEvent.Item event )
public static void onItemColours( RegisterColorHandlersEvent.Item event )
{
if( Registry.ModItems.DISK == null || Registry.ModBlocks.TURTLE_NORMAL == null )
{
@ -87,17 +88,17 @@ public static void onItemColours( ColorHandlerEvent.Item event )
return;
}
event.getItemColors().register(
event.register(
( stack, layer ) -> layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF,
Registry.ModItems.DISK.get()
);
event.getItemColors().register(
event.register(
( stack, layer ) -> layer == 1 ? ItemTreasureDisk.getColour( stack ) : 0xFFFFFF,
Registry.ModItems.TREASURE_DISK.get()
);
event.getItemColors().register( ( stack, layer ) -> {
event.register( ( stack, layer ) -> {
switch( layer )
{
case 0:
@ -123,14 +124,6 @@ public static void onItemColours( ColorHandlerEvent.Item event )
@SubscribeEvent
public static void setupClient( FMLClientSetupEvent event )
{
// While turtles themselves are not transparent, their upgrades may be.
ItemBlockRenderTypes.setRenderLayer( Registry.ModBlocks.TURTLE_NORMAL.get(), RenderType.translucent() );
ItemBlockRenderTypes.setRenderLayer( Registry.ModBlocks.TURTLE_ADVANCED.get(), RenderType.translucent() );
// Monitors' textures have transparent fronts and so count as cutouts.
ItemBlockRenderTypes.setRenderLayer( Registry.ModBlocks.MONITOR_NORMAL.get(), RenderType.cutout() );
ItemBlockRenderTypes.setRenderLayer( Registry.ModBlocks.MONITOR_ADVANCED.get(), RenderType.cutout() );
// Setup TESRs
BlockEntityRenderers.register( Registry.ModBlockEntities.MONITOR_NORMAL.get(), TileEntityMonitorRenderer::new );
BlockEntityRenderers.register( Registry.ModBlockEntities.MONITOR_ADVANCED.get(), TileEntityMonitorRenderer::new );

View File

@ -23,7 +23,7 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawSelectionEvent;
import net.minecraftforge.client.event.RenderHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@ -41,7 +41,7 @@ private CableHighlightRenderer()
* @see net.minecraft.client.renderer.LevelRenderer#renderHitOutline
*/
@SubscribeEvent
public static void drawHighlight( DrawSelectionEvent.HighlightBlock event )
public static void drawHighlight( RenderHighlightEvent.Block event )
{
BlockHitResult hit = event.getTarget();
BlockPos pos = hit.getBlockPos();

View File

@ -15,7 +15,7 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@ -25,7 +25,7 @@
public class DebugOverlay
{
@SubscribeEvent
public static void onRenderText( RenderGameOverlayEvent.Text event )
public static void onRenderText( CustomizeGuiOverlayEvent.DebugText event )
{
Minecraft minecraft = Minecraft.getInstance();
if( !minecraft.options.renderDebug || minecraft.level == null ) return;

View File

@ -18,7 +18,7 @@
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawSelectionEvent;
import net.minecraftforge.client.event.RenderHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@ -38,7 +38,7 @@ private MonitorHighlightRenderer()
}
@SubscribeEvent
public static void drawHighlight( DrawSelectionEvent.HighlightBlock event )
public static void drawHighlight( RenderHighlightEvent.Block event )
{
// Preserve normal behaviour when crouching.
if( event.getCamera().getEntity().isCrouching() ) return;

View File

@ -34,7 +34,7 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.ModelData;
import javax.annotation.Nonnull;
import java.util.List;
@ -165,10 +165,10 @@ private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, int[] tints )
{
random.setSeed( 0 );
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random, EmptyModelData.INSTANCE ), tints );
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random, ModelData.EMPTY, null ), tints );
for( Direction facing : DirectionUtil.FACINGS )
{
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random, EmptyModelData.INSTANCE ), tints );
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random, ModelData.EMPTY, null ), tints );
}
}
@ -185,10 +185,10 @@ private static void renderQuads( @Nonnull PoseStack transform, @Nonnull VertexCo
if( idx >= 0 && idx < tints.length ) tint = tints[bakedquad.getTintIndex()];
}
float f = (float) (tint >> 16 & 255) / 255.0F;
float f1 = (float) (tint >> 8 & 255) / 255.0F;
float f2 = (float) (tint & 255) / 255.0F;
buffer.putBulkData( matrix, bakedquad, f, f1, f2, lightmapCoord, overlayLight, true );
float r = (float) (tint >> 16 & 255) / 255.0F;
float g = (float) (tint >> 8 & 255) / 255.0F;
float b = (float) (tint & 255) / 255.0F;
buffer.putBulkData( matrix, bakedquad, r, g, b, lightmapCoord, overlayLight );
}
}
}

View File

@ -0,0 +1,60 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.render;
import com.mojang.math.Transformation;
import dan200.computercraft.api.client.TransformedModel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.BakedModelWrapper;
import net.minecraftforge.client.model.IQuadTransformer;
import net.minecraftforge.client.model.data.ModelData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
import java.util.List;
public class TransformedBakedModel extends BakedModelWrapper<BakedModel>
{
private final Transformation transformation;
private final boolean isIdentity;
public TransformedBakedModel( BakedModel model, Transformation transformation )
{
super( model );
this.transformation = transformation;
isIdentity = transformation.isIdentity();
}
public TransformedBakedModel( TransformedModel model )
{
this( model.getModel(), model.getMatrix() );
}
@Nonnull
@Override
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, @Nonnull RandomSource rand )
{
return getQuads( state, side, rand, ModelData.EMPTY, null );
}
@Override
public @NotNull List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, @NotNull RandomSource rand, @NotNull ModelData extraData, @Nullable RenderType renderType )
{
List<BakedQuad> quads = originalModel.getQuads( state, side, rand, extraData, renderType );
return isIdentity ? quads : IQuadTransformer.applying( transformation ).process( quads );
}
public TransformedBakedModel composeWith( Transformation other )
{
return new TransformedBakedModel( originalModel, other.compose( transformation ) );
}
}

View File

@ -13,11 +13,10 @@
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.GsonHelper;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.IModelLoader;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
import net.minecraftforge.client.model.geometry.IGeometryLoader;
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
import javax.annotation.Nonnull;
import java.util.Collection;
@ -25,7 +24,7 @@
import java.util.Set;
import java.util.function.Function;
public final class TurtleModelLoader implements IModelLoader<TurtleModelLoader.TurtleModel>
public final class TurtleModelLoader implements IGeometryLoader<TurtleModelLoader.TurtleModel>
{
private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_colour" );
@ -35,20 +34,15 @@ private TurtleModelLoader()
{
}
@Override
public void onResourceManagerReload( @Nonnull ResourceManager manager )
{
}
@Nonnull
@Override
public TurtleModel read( @Nonnull JsonDeserializationContext deserializationContext, @Nonnull JsonObject modelContents )
public TurtleModel read( @Nonnull JsonObject modelContents, @Nonnull JsonDeserializationContext deserializationContext )
{
ResourceLocation model = new ResourceLocation( GsonHelper.getAsString( modelContents, "model" ) );
return new TurtleModel( model );
}
public static final class TurtleModel implements IModelGeometry<TurtleModel>
public static final class TurtleModel implements IUnbakedGeometry<TurtleModel>
{
private final ResourceLocation family;
@ -58,7 +52,7 @@ private TurtleModel( ResourceLocation family )
}
@Override
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
public Collection<Material> getMaterials( IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
{
Set<Material> materials = new HashSet<>();
materials.addAll( modelGetter.apply( family ).getMaterials( modelGetter, missingTextureErrors ) );
@ -67,7 +61,7 @@ public Collection<Material> getTextures( IModelConfiguration owner, Function<Res
}
@Override
public BakedModel bake( IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState transform, ItemOverrides overrides, ResourceLocation modelLocation )
public BakedModel bake( IGeometryBakingContext owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState transform, ItemOverrides overrides, ResourceLocation modelLocation )
{
return new TurtleSmartItemModel(
bakery.bake( family, transform, spriteGetter ),

View File

@ -1,153 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.render;
import com.mojang.math.Transformation;
import dan200.computercraft.api.client.TransformedModel;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import net.minecraftforge.client.model.pipeline.TRSRTransformer;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
public class TurtleMultiModel implements BakedModel
{
private final BakedModel baseModel;
private final BakedModel overlayModel;
private final Transformation generalTransform;
private final TransformedModel leftUpgradeModel;
private final TransformedModel rightUpgradeModel;
private List<BakedQuad> generalQuads = null;
private final Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Transformation generalTransform, TransformedModel leftUpgradeModel, TransformedModel rightUpgradeModel )
{
// Get the models
this.baseModel = baseModel;
this.overlayModel = overlayModel;
this.leftUpgradeModel = leftUpgradeModel;
this.rightUpgradeModel = rightUpgradeModel;
this.generalTransform = generalTransform;
}
@Nonnull
@Override
@Deprecated
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull RandomSource rand )
{
return getQuads( state, side, rand, EmptyModelData.INSTANCE );
}
@Nonnull
@Override
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull RandomSource rand, @Nonnull IModelData data )
{
if( side != null )
{
if( !faceQuads.containsKey( side ) ) faceQuads.put( side, buildQuads( state, side, rand ) );
return faceQuads.get( side );
}
else
{
if( generalQuads == null ) generalQuads = buildQuads( state, side, rand );
return generalQuads;
}
}
private List<BakedQuad> buildQuads( BlockState state, Direction side, RandomSource rand )
{
ArrayList<BakedQuad> quads = new ArrayList<>();
transformQuadsTo( quads, baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), generalTransform );
if( overlayModel != null )
{
transformQuadsTo( quads, overlayModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), generalTransform );
}
if( leftUpgradeModel != null )
{
Transformation upgradeTransform = generalTransform.compose( leftUpgradeModel.getMatrix() );
transformQuadsTo( quads, leftUpgradeModel.getModel().getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
}
if( rightUpgradeModel != null )
{
Transformation upgradeTransform = generalTransform.compose( rightUpgradeModel.getMatrix() );
transformQuadsTo( quads, rightUpgradeModel.getModel().getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
}
quads.trimToSize();
return quads;
}
@Override
public boolean useAmbientOcclusion()
{
return baseModel.useAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return baseModel.isGui3d();
}
@Override
public boolean isCustomRenderer()
{
return baseModel.isCustomRenderer();
}
@Override
public boolean usesBlockLight()
{
return baseModel.usesBlockLight();
}
@Nonnull
@Override
@Deprecated
public TextureAtlasSprite getParticleIcon()
{
return baseModel.getParticleIcon();
}
@Nonnull
@Override
@Deprecated
public net.minecraft.client.renderer.block.model.ItemTransforms getTransforms()
{
return baseModel.getTransforms();
}
@Nonnull
@Override
public ItemOverrides getOverrides()
{
return ItemOverrides.EMPTY;
}
private void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> quads, Transformation transform )
{
for( BakedQuad quad : quads )
{
BakedQuadBuilder builder = new BakedQuadBuilder();
TRSRTransformer transformer = new TRSRTransformer( builder, transform );
quad.pipe( transformer );
output.add( builder.build() );
}
}
}

View File

@ -7,35 +7,27 @@
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Transformation;
import dan200.computercraft.api.client.TransformedModel;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.BakedModelWrapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TurtleSmartItemModel implements BakedModel
public class TurtleSmartItemModel extends BakedModelWrapper<BakedModel>
{
private static final Transformation identity, flip;
@ -49,7 +41,7 @@ public class TurtleSmartItemModel implements BakedModel
flip = new Transformation( stack.last().pose() );
}
private static record TurtleModelCombination(
private record TurtleModelCombination(
boolean colour,
ITurtleUpgrade leftUpgrade,
ITurtleUpgrade rightUpgrade,
@ -63,112 +55,64 @@ private static record TurtleModelCombination(
private final BakedModel familyModel;
private final BakedModel colourModel;
private final HashMap<TurtleModelCombination, BakedModel> cachedModels = new HashMap<>();
private final ItemOverrides overrides;
private final Map<TurtleModelCombination, List<BakedModel>> cachedModels = new HashMap<>();
public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel )
{
super( familyModel );
this.familyModel = familyModel;
this.colourModel = colourModel;
overrides = new ItemOverrides()
{
@Nonnull
@Override
public BakedModel resolve( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientLevel world, @Nullable LivingEntity entity, int random )
{
ItemTurtle turtle = (ItemTurtle) stack.getItem();
int colour = turtle.getColour( stack );
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.LEFT );
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.RIGHT );
ResourceLocation overlay = turtle.getOverlay( stack );
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS;
String label = turtle.getLabel( stack );
boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
BakedModel model = cachedModels.get( combo );
if( model == null ) cachedModels.put( combo, model = buildModel( combo ) );
return model;
}
};
}
@Nonnull
@Override
public ItemOverrides getOverrides()
public BakedModel applyTransform( @Nonnull ItemTransforms.TransformType cameraTransformType, @Nonnull PoseStack poseStack, boolean applyLeftHandTransform )
{
return overrides;
originalModel.applyTransform( cameraTransformType, poseStack, applyLeftHandTransform );
return this;
}
private BakedModel buildModel( TurtleModelCombination combo )
@Nonnull
@Override
public List<BakedModel> getRenderPasses( ItemStack stack, boolean fabulous )
{
ItemTurtle turtle = (ItemTurtle) stack.getItem();
int colour = turtle.getColour( stack );
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.LEFT );
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.RIGHT );
ResourceLocation overlay = turtle.getOverlay( stack );
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS;
String label = turtle.getLabel( stack );
boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
return cachedModels.computeIfAbsent( combo, this::buildModel );
}
private List<BakedModel> buildModel( TurtleModelCombination combo )
{
Minecraft mc = Minecraft.getInstance();
ModelManager modelManager = mc.getItemRenderer().getItemModelShaper().getModelManager();
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas );
BakedModel baseModel = combo.colour ? colourModel : familyModel;
BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null;
Transformation transform = combo.flip ? flip : identity;
TransformedModel leftModel = combo.leftUpgrade != null ? combo.leftUpgrade.getModel( null, TurtleSide.LEFT ) : null;
TransformedModel rightModel = combo.rightUpgrade != null ? combo.rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null;
return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel, rightModel );
var transformation = combo.flip ? flip : identity;
ArrayList<BakedModel> parts = new ArrayList<>( 4 );
parts.add( new TransformedBakedModel( combo.colour() ? colourModel : familyModel, transformation ) );
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay(), combo.christmas() );
if( overlayModelLocation != null )
{
parts.add( new TransformedBakedModel( modelManager.getModel( overlayModelLocation ), transformation ) );
}
if( combo.leftUpgrade() != null )
{
parts.add( new TransformedBakedModel( combo.leftUpgrade().getModel( null, TurtleSide.LEFT ) ).composeWith( transformation ) );
}
if( combo.rightUpgrade() != null )
{
parts.add( new TransformedBakedModel( combo.rightUpgrade().getModel( null, TurtleSide.RIGHT ) ).composeWith( transformation ) );
}
return parts;
}
@Nonnull
@Override
@Deprecated
public List<BakedQuad> getQuads( BlockState state, Direction facing, @Nonnull RandomSource rand )
{
return familyModel.getQuads( state, facing, rand );
}
@Nonnull
@Override
@Deprecated
public List<BakedQuad> getQuads( BlockState state, Direction facing, @Nonnull RandomSource rand, @Nonnull IModelData data )
{
return familyModel.getQuads( state, facing, rand, data );
}
@Override
public boolean useAmbientOcclusion()
{
return familyModel.useAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return familyModel.isGui3d();
}
@Override
public boolean isCustomRenderer()
{
return familyModel.isCustomRenderer();
}
@Override
public boolean usesBlockLight()
{
return familyModel.usesBlockLight();
}
@Nonnull
@Override
@Deprecated
public TextureAtlasSprite getParticleIcon()
{
return familyModel.getParticleIcon();
}
@Nonnull
@Override
@Deprecated
public ItemTransforms getTransforms()
{
return familyModel.getTransforms();
}
}

View File

@ -8,9 +8,9 @@
import dan200.computercraft.shared.Registry;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
@Mod.EventBusSubscriber( bus = Mod.EventBusSubscriber.Bus.MOD )
public class Generators

View File

@ -24,7 +24,7 @@
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelData;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -35,7 +35,7 @@
/**
* Provides custom block breaking progress for modems, so it only applies to the current part.
*
* @see BlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer, IModelData)
* @see BlockRenderDispatcher#renderBreakingTexture(BlockState, BlockPos, BlockAndTintGetter, PoseStack, VertexConsumer, ModelData)
*/
@Mixin( BlockRenderDispatcher.class )
public class BlockRenderDispatcherMixin
@ -53,13 +53,13 @@ public class BlockRenderDispatcherMixin
private ModelBlockRenderer modelRenderer;
@Inject(
method = "name=/^renderBreakingTexture/ desc=/IModelData;\\)V$/",
method = "name=/^renderBreakingTexture/ desc=/ModelData;\\)V$/",
at = @At( "HEAD" ),
cancellable = true,
require = 0 // This isn't critical functionality, so don't worry if we can't apply it.
)
public void renderBlockDamage(
BlockState state, BlockPos pos, BlockAndTintGetter world, PoseStack pose, VertexConsumer buffers, IModelData modelData,
BlockState state, BlockPos pos, BlockAndTintGetter world, PoseStack pose, VertexConsumer buffers, ModelData modelData,
CallbackInfo info
)
{
@ -85,6 +85,6 @@ public void renderBlockDamage(
BakedModel model = blockModelShaper.getBlockModel( newState );
long seed = newState.getSeed( pos );
modelRenderer.tesselateBlock( world, model, newState, pos, pose, buffers, true, random, seed, OverlayTexture.NO_OVERLAY, modelData );
modelRenderer.tesselateBlock( world, model, newState, pos, pose, buffers, true, random, seed, OverlayTexture.NO_OVERLAY, modelData, null );
}
}

View File

@ -73,7 +73,7 @@ public static void onContainerOpen( PlayerContainerEvent.Open event )
IComputer computer = ((IContainerComputer) container).getComputer();
if( computer instanceof ServerComputer )
{
((ServerComputer) computer).sendTerminalState( event.getPlayer() );
((ServerComputer) computer).sendTerminalState( event.getEntity() );
}
}
}

View File

@ -6,8 +6,6 @@
package dan200.computercraft.shared;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.apis.http.NetworkUtils;
import dan200.computercraft.core.apis.http.options.Action;
@ -367,6 +365,4 @@ public static void sync( ModConfigEvent.Reloading event )
{
sync( event.getConfig() );
}
private static final Converter<String, String> converter = CaseFormat.LOWER_CAMEL.converterTo( CaseFormat.UPPER_UNDERSCORE );
}

View File

@ -13,7 +13,10 @@
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
import dan200.computercraft.shared.command.arguments.*;
import dan200.computercraft.shared.command.arguments.ComputerArgumentType;
import dan200.computercraft.shared.command.arguments.ComputersArgumentType;
import dan200.computercraft.shared.command.arguments.RepeatArgumentType;
import dan200.computercraft.shared.command.arguments.TrackingFieldArgumentType;
import dan200.computercraft.shared.common.ColourableRecipe;
import dan200.computercraft.shared.common.ContainerHeldItem;
import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider;
@ -164,7 +167,7 @@ private static BlockBehaviour.Properties modemProperties()
public static class ModBlockEntities
{
static final DeferredRegister<BlockEntityType<?>> TILES = DeferredRegister.create( ForgeRegistries.BLOCK_ENTITIES, ComputerCraft.MOD_ID );
static final DeferredRegister<BlockEntityType<?>> TILES = DeferredRegister.create( ForgeRegistries.BLOCK_ENTITY_TYPES, ComputerCraft.MOD_ID );
private static <T extends BlockEntity> RegistryObject<BlockEntityType<T>> ofBlock( RegistryObject<? extends Block> block, FixedPointTileEntityType.FixedPointBlockEntitySupplier<T> factory )
{
@ -283,7 +286,7 @@ public static class ModPocketUpgradeSerialisers
public static class ModContainers
{
static final DeferredRegister<MenuType<?>> CONTAINERS = DeferredRegister.create( ForgeRegistries.CONTAINERS, ComputerCraft.MOD_ID );
static final DeferredRegister<MenuType<?>> CONTAINERS = DeferredRegister.create( ForgeRegistries.MENU_TYPES, ComputerCraft.MOD_ID );
public static final RegistryObject<MenuType<ContainerComputerBase>> COMPUTER = CONTAINERS.register( "computer",
() -> ContainerData.toType( ComputerContainerData::new, ComputerMenuWithoutInventory::new ) );
@ -317,7 +320,7 @@ static class ModArgumentTypes
@SuppressWarnings( "unchecked" )
private static <T extends ArgumentType<?>> void registerUnsafe( String name, Class<T> type, ArgumentTypeInfo<?, ?> serializer )
{
ARGUMENT_TYPES.register( name, () -> ArgumentTypeInfos.registerByClass( type, (ArgumentTypeInfo<T, ?>)serializer ) );
ARGUMENT_TYPES.register( name, () -> ArgumentTypeInfos.registerByClass( type, (ArgumentTypeInfo<T, ?>) serializer ) );
}
private static <T extends ArgumentType<?>> void register( String name, Class<T> type, ArgumentTypeInfo<T, ?> serializer )

View File

@ -104,7 +104,7 @@ private static <T extends NetworkMessage> void registerMainThread( int id, Netwo
network.messageBuilder( type, id, direction )
.encoder( NetworkMessage::toBytes )
.decoder( decoder )
.consumer( ( packet, contextSup ) -> {
.consumerMainThread( ( packet, contextSup ) -> {
NetworkEvent.Context context = contextSup.get();
context.enqueueWork( () -> packet.handle( context ) );
context.setPacketHandled( true );

View File

@ -30,7 +30,7 @@ public interface ContainerData
default void open( Player player, MenuProvider owner )
{
NetworkHooks.openGui( (ServerPlayer) player, owner, this::toBytes );
NetworkHooks.openScreen( (ServerPlayer) player, owner, this::toBytes );
}
static <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> toType( Function<FriendlyByteBuf, T> reader, Factory<C, T> factory )

View File

@ -120,7 +120,7 @@ public InteractionResult onActivate( Player player, InteractionHand hand, BlockH
// Open the GUI
if( !getLevel().isClientSide && isUsable( player ) )
{
NetworkHooks.openGui( (ServerPlayer) player, this );
NetworkHooks.openScreen( (ServerPlayer) player, this );
}
return InteractionResult.SUCCESS;
}

View File

@ -30,7 +30,7 @@ class GenericPeripheral implements IDynamicPeripheral
GenericPeripheral( BlockEntity tile, String name, Set<String> additionalTypes, List<SaturatedMethod> methods )
{
ResourceLocation type = ForgeRegistries.BLOCK_ENTITIES.getKey( tile.getType() );
ResourceLocation type = ForgeRegistries.BLOCK_ENTITY_TYPES.getKey( tile.getType() );
this.tile = tile;
this.type = name != null ? name : (type != null ? type.toString() : "unknown");
this.additionalTypes = additionalTypes;

View File

@ -11,13 +11,11 @@
import dan200.computercraft.shared.network.client.TerminalState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.world.ChunkWatchEvent;
import net.minecraftforge.event.level.ChunkWatchEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@ -28,7 +26,6 @@
public final class MonitorWatcher
{
private static final Queue<TileMonitor> watching = new ArrayDeque<>();
private static final Queue<PlayerUpdate> playerUpdates = new ArrayDeque<>();
private MonitorWatcher()
{
@ -46,47 +43,28 @@ static void enqueue( TileMonitor monitor )
@SubscribeEvent
public static void onWatch( ChunkWatchEvent.Watch event )
{
// Get the current chunk if it has been loaded. This is safe as, if the chunk hasn't been loaded yet, then the
// monitor will have no contents, and so we won't need to send an update anyway.
ChunkPos chunkPos = event.getPos();
LevelChunk chunk = event.getWorld().getChunkSource().getChunkNow( chunkPos.x, chunkPos.z );
if( chunk == null ) return;
for( BlockEntity te : chunk.getBlockEntities().values() )
// Find all origin monitors who are not already on the queue and send the
// monitor data to the player.
for( BlockEntity te : event.getChunk().getBlockEntities().values() )
{
// Find all origin monitors who are not already on the queue.
if( !(te instanceof TileMonitor monitor) ) continue;
ServerMonitor serverMonitor = getMonitor( monitor );
if( serverMonitor == null || monitor.enqueued ) continue;
// The chunk hasn't been sent to the client yet, so we can't send an update. Do it on tick end.
playerUpdates.add( new PlayerUpdate( event.getPlayer(), monitor ) );
TerminalState state = monitor.cached;
if( state == null ) state = monitor.cached = serverMonitor.write();
NetworkHandler.sendToPlayer( event.getPlayer(), new MonitorClientMessage( monitor.getBlockPos(), state ) );
}
}
@SubscribeEvent
public static void onTick( TickEvent.ServerTickEvent event )
{
// Find all enqueued monitors and send their contents to all nearby players.
if( event.phase != TickEvent.Phase.END ) return;
PlayerUpdate playerUpdate;
while( (playerUpdate = playerUpdates.poll()) != null )
{
TileMonitor tile = playerUpdate.monitor;
if( tile.enqueued || tile.isRemoved() ) continue;
ServerMonitor monitor = getMonitor( tile );
if( monitor == null ) continue;
// Some basic sanity checks to the player. It's possible they're no longer within range, but that's harder
// to track efficiently.
ServerPlayer player = playerUpdate.player;
if( !player.isAlive() || player.getLevel() != tile.getLevel() ) continue;
NetworkHandler.sendToPlayer( playerUpdate.player, new MonitorClientMessage( tile.getBlockPos(), getState( tile, monitor ) ) );
}
long limit = ComputerCraft.monitorBandwidth;
boolean obeyLimit = limit > 0;
@ -125,16 +103,4 @@ private static TerminalState getState( TileMonitor tile, ServerMonitor monitor )
if( state == null ) state = tile.cached = monitor.write();
return state;
}
private static final class PlayerUpdate
{
final ServerPlayer player;
final TileMonitor monitor;
private PlayerUpdate( ServerPlayer player, TileMonitor monitor )
{
this.player = player;
this.monitor = monitor;
}
}
}

View File

@ -99,7 +99,7 @@ public InteractionResult onActivate( Player player, InteractionHand hand, BlockH
if( !getLevel().isClientSide && isUsable( player ) )
{
NetworkHooks.openGui( (ServerPlayer) player, this );
NetworkHooks.openScreen( (ServerPlayer) player, this );
}
return InteractionResult.SUCCESS;
}

View File

@ -37,7 +37,7 @@ public int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStac
ItemStack stack = turtle.getItemHandler().extractItem( slot, limit, false );
int fuelToGive = fuelPerItem * stack.getCount();
// Store the replacement item in the inventory
ItemStack replacementStack = stack.getItem().getContainerItem( stack );
ItemStack replacementStack = ForgeHooks.getCraftingRemainingItem( stack );
if( !replacementStack.isEmpty() )
{
ItemStack remainder = InventoryUtil.storeItems( replacementStack, turtle.getItemHandler(), turtle.getSelectedSlot() );

View File

@ -42,7 +42,7 @@
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.ToolActions;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.level.BlockEvent;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;

View File

@ -13,7 +13,7 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@ -80,10 +80,10 @@ private static void handleDrops( ItemStack stack )
}
@SubscribeEvent( priority = EventPriority.HIGHEST )
public static void onEntitySpawn( EntityJoinWorldEvent event )
public static void onEntitySpawn( EntityJoinLevelEvent event )
{
// Capture any nearby item spawns
if( dropWorld == event.getWorld() && event.getEntity() instanceof ItemEntity
if( dropWorld == event.getLevel() && event.getEntity() instanceof ItemEntity
&& dropBounds.contains( event.getEntity().position() ) )
{
handleDrops( ((ItemEntity) event.getEntity()).getItem() );

View File

@ -21,6 +21,6 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a
[[dependencies.computercraft]]
modId="forge"
mandatory=true
versionRange="[41.0.38,42)"
versionRange="[41.0.98,42)"
ordering="NONE"
side="BOTH"

View File

@ -1,5 +1,6 @@
{
"parent": "block/cube",
"render_type": "cutout",
"textures": {
"particle": "#front",
"down": "#top",

View File

@ -1,5 +1,6 @@
{
"parent": "block/block",
"render_type": "translucent",
"textures": {
"particle": "#texture"
},

View File

@ -137,7 +137,7 @@
run(startSequence()).thenSucceed()
}
private fun getName(type: BlockEntityType<*>): ResourceLocation = ForgeRegistries.BLOCK_ENTITIES.getKey(type)!!
private fun getName(type: BlockEntityType<*>): ResourceLocation = ForgeRegistries.BLOCK_ENTITY_TYPES.getKey(type)!!
fun <T : BlockEntity> GameTestHelper.getBlockEntity(pos: BlockPos, type: BlockEntityType<T>): T {
val tile = getBlockEntity(pos)

View File

@ -29,7 +29,7 @@ private ClientHooks()
}
@SubscribeEvent
public static void onGuiInit( ScreenEvent.InitScreenEvent event )
public static void onGuiInit( ScreenEvent.Init event )
{
if( triggered || !(event.getScreen() instanceof TitleScreen) ) return;
triggered = true;