Updated forcefield camouflage to 1.10 (first pass)

This commit is contained in:
LemADEC 2017-12-02 13:17:55 +01:00
parent d54e16fa8f
commit b37e453ac4
8 changed files with 285 additions and 84 deletions

View file

@ -1,23 +1,31 @@
package cr0s.warpdrive;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.data.BlockProperties;
import cr0s.warpdrive.data.VectorI;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.command.EntitySelector;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.fml.server.FMLServerHandler;
import java.io.File;
@ -42,6 +50,12 @@ import java.util.Set;
public class Commons {
private static final String CHAR_FORMATTING = "" + (char)167;
private static final List<EnumBlockRenderType> ALLOWED_RENDER_TYPES = Arrays.asList(
EnumBlockRenderType.INVISIBLE,
// EnumBlockRenderType.LIQUID,
EnumBlockRenderType.ENTITYBLOCK_ANIMATED,
EnumBlockRenderType.MODEL
);
public static String updateEscapeCodes(final String message) {
return message
@ -532,4 +546,41 @@ public class Commons {
}
return direction.ordinal();
}
public static boolean isValidCamouflage(final IBlockState blockState) {
// fast check
if ( blockState == null
|| blockState == Blocks.AIR
|| !ALLOWED_RENDER_TYPES.contains(blockState.getRenderType())
|| Dictionary.BLOCKS_NOCAMOUFLAGE.contains(blockState.getBlock()) ) {
return false;
}
if (blockState instanceof IExtendedBlockState) {
// own camouflage blocks
try {
((IExtendedBlockState) blockState).getValue(BlockProperties.CAMOUFLAGE);
// failed: add it to the fast check
WarpDrive.logger.error(String.format("Recursive camouflage block detected for block state %s, updating dictionary with %s = NOCAMOUFLAGE dictionary to prevent further errors",
blockState,
blockState.getBlock().getRegistryName()));
Dictionary.BLOCKS_NOCAMOUFLAGE.add(blockState.getBlock());
return false;
} catch (IllegalArgumentException exception) {
// success: this is valid block for us
}
// other mods camouflage blocks
for (IUnlistedProperty<?> property : ((IExtendedBlockState) blockState).getUnlistedNames()) {
if (property.getType().toString().contains("IBlockState")) {
// failed: add it to the fast check
WarpDrive.logger.error(String.format("Suspicious camouflage block detected for block state %s, updating dictionary with %s = NOCAMOUFLAGE dictionary to prevent further errors",
blockState,
blockState.getBlock().getRegistryName()));
Dictionary.BLOCKS_NOCAMOUFLAGE.add(blockState.getBlock());
return false;
}
}
}
return true;
}
}

View file

@ -1,13 +1,17 @@
package cr0s.warpdrive.block.forcefield;
import cr0s.warpdrive.Commons;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IDamageReceiver;
import cr0s.warpdrive.block.hull.BlockHullGlass;
import cr0s.warpdrive.client.ClientProxy;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.BlockProperties;
import cr0s.warpdrive.data.EnumPermissionNode;
import cr0s.warpdrive.data.ForceFieldSetup;
import cr0s.warpdrive.data.Vector3;
import cr0s.warpdrive.data.VectorI;
import cr0s.warpdrive.event.ModelBakeEventHandler;
import java.util.List;
import java.util.Random;
@ -16,9 +20,11 @@ import net.minecraft.block.BlockGlass;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
@ -40,6 +46,9 @@ import net.minecraft.world.Explosion;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@ -62,14 +71,18 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
setUnlocalizedName("warpdrive.forcefield.block" + tier);
setBlockUnbreakable();
setDefaultState(getDefaultState().withProperty(FREQUENCY, 0));
setDefaultState(getDefaultState()
.withProperty(FREQUENCY, 0)
);
GameRegistry.registerTileEntity(TileEntityForceField.class, WarpDrive.PREFIX + registryName);
}
@Nonnull
@Override
protected BlockStateContainer createBlockState() {
return new BlockStateContainer(this, FREQUENCY);
return new ExtendedBlockState(this,
new IProperty[] { FREQUENCY },
new IUnlistedProperty[] { BlockProperties.CAMOUFLAGE });
}
@SuppressWarnings("deprecation")
@ -92,6 +105,25 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
return state.getValue(FREQUENCY);
}
@Nonnull
@Override
public IBlockState getExtendedState(@Nonnull IBlockState blockState, IBlockAccess blockAccess, BlockPos blockPos) {
if (!(blockState instanceof IExtendedBlockState)) {
return blockState;
}
final TileEntity tileEntity = blockAccess.getTileEntity(blockPos);
if (!(tileEntity instanceof TileEntityForceField)) {
return blockState;
}
final TileEntityForceField tileEntityForceField = (TileEntityForceField) tileEntity;
IBlockState blockStateCamouflage = tileEntityForceField.cache_blockStateCamouflage;
if (!Commons.isValidCamouflage(blockStateCamouflage)) {
blockStateCamouflage = Blocks.AIR.getDefaultState();
}
return ((IExtendedBlockState) blockState)
.withProperty(BlockProperties.CAMOUFLAGE, blockStateCamouflage);
}
@Nullable
@Override
public ItemBlock createItemBlock() {
@ -104,6 +136,19 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
return new TileEntityForceField();
}
@SideOnly(Side.CLIENT)
@Override
public void modelInitialisation() {
final Item item = Item.getItemFromBlock(this);
ClientProxy.modelInitialisation(item);
// register camouflage
for (Integer integer : FREQUENCY.getAllowedValues()) {
final String variant = String.format("%s=%d", FREQUENCY.getName(), integer);
ModelBakeEventHandler.registerCamouflage(new ModelResourceLocation(getRegistryName(), variant));
}
}
@Override
public boolean isVisuallyOpaque() {
return false;
@ -316,25 +361,14 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
// find explosion strength, defaults to no effect
double strength = 0.0D;
if (entity == null && (explosionX == Math.rint(explosionX)) && (explosionY == Math.rint(explosionY)) && (explosionZ == Math.rint(explosionZ)) ) {
<<<<<<< HEAD
// IC2 Reactor blowing up => block is already air
Block block = world.getBlock((int)explosionX, (int)explosionY, (int)explosionZ);
TileEntity tileEntity = world.getTileEntity((int)explosionX, (int)explosionY, (int)explosionZ);
=======
// IC2 Reactor blowing up => bloc is already air
IBlockState blockState = world.getBlockState(new BlockPos((int)explosionX, (int)explosionY, (int)explosionZ));
TileEntity tileEntity = world.getTileEntity(new BlockPos((int)explosionX, (int)explosionY, (int)explosionZ));
>>>>>>> MC1.10
if (enableFirstHit && WarpDriveConfig.LOGGING_FORCEFIELD) {
WarpDrive.logger.info("Block at location is " + blockState.getBlock() + " " + blockState.getBlock().getUnlocalizedName() + " with tileEntity " + tileEntity);
}
<<<<<<< HEAD
// explosion with no entity and block removed, hence we can't compute the energy impact => boosting explosion resistance
return 2.0F * super.getExplosionResistance(entity, world, x, y, z, explosionX, explosionY, explosionZ);
=======
// explosion with no entity and block removed, hence we can compute the energy impact => boosting explosion resistance
return 2.0F * super.getExplosionResistance(entity, world, blockPos, explosionX, explosionY, explosionZ);
>>>>>>> MC1.10
}
if (entity != null) {

View file

@ -11,4 +11,6 @@ public class BlockProperties {
public static final PropertyDirection FACING = PropertyDirection.create("facing");
public static final PropertyEnum<EnumSirenType> SIREN_TYPE = PropertyEnum.create("siren_type", EnumSirenType.class);
public static final PropertyEnum<EnumTier> TIER = PropertyEnum.create("tier", EnumTier.class);
public static final UnlistedPropertyBlockState CAMOUFLAGE = new UnlistedPropertyBlockState("camouflage");
}

View file

@ -6,15 +6,12 @@ import cr0s.warpdrive.api.IForceFieldShape;
import cr0s.warpdrive.api.IForceFieldUpgrade;
import cr0s.warpdrive.api.IForceFieldUpgradeEffector;
import cr0s.warpdrive.block.forcefield.TileEntityForceFieldProjector;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.WarpDriveConfig;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@ -48,8 +45,6 @@ public class ForceFieldSetup extends GlobalPosition {
private IBlockState blockStateCamouflage;
private int colorMultiplierCamouflage;
private int lightCamouflage;
private static final List<Integer> ALLOWED_RENDER_TYPES = Arrays.asList(
0, 1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 41);
private final HashMap<IForceFieldUpgradeEffector, Float> upgrades = new HashMap<>(EnumForceFieldUpgrade.length);
public final Collection<IInventory> inventories = new ArrayList<>(12);
@ -100,26 +95,22 @@ public class ForceFieldSetup extends GlobalPosition {
return false; // TODO
}
private static boolean isValidCamouflage(final IBlockState blockState) {
return blockState != null && blockState != Blocks.AIR && ALLOWED_RENDER_TYPES.contains(blockState.getRenderType()) && !Dictionary.BLOCKS_NOCAMOUFLAGE.contains(blockState.getBlock());
}
public IBlockState getCamouflageBlockState() {
if (isValidCamouflage(blockStateCamouflage)) {
if (Commons.isValidCamouflage(blockStateCamouflage)) {
return blockStateCamouflage;
}
return Blocks.AIR.getDefaultState();
}
public int getCamouflageColorMultiplier() {
if (isValidCamouflage(blockStateCamouflage)) {
if (Commons.isValidCamouflage(blockStateCamouflage)) {
return colorMultiplierCamouflage;
}
return 0;
}
public int getCamouflageLight() {
if (isValidCamouflage(blockStateCamouflage)) {
if (Commons.isValidCamouflage(blockStateCamouflage)) {
return lightCamouflage;
}
return 0;
@ -192,7 +183,7 @@ public class ForceFieldSetup extends GlobalPosition {
if (upgradeEffector == EnumForceFieldUpgrade.CAMOUFLAGE) {
BlockPos blockPosCamouflage = tileEntity.getPos().offset(EnumFacing.UP);
IBlockState blockStateCandidate = tileEntity.getWorld().getBlockState(blockPosCamouflage);
if (isValidCamouflage(blockStateCandidate)) {
if (Commons.isValidCamouflage(blockStateCandidate)) {
blockStateCamouflage = blockStateCandidate;
colorMultiplierCamouflage = 0x808080; // blockStateCandidate.colorMultiplier(tileEntity.getWorld(), blockPosCamouflage);
lightCamouflage = blockStateCandidate.getLightValue(tileEntity.getWorld(), blockPosCamouflage);

View file

@ -0,0 +1,34 @@
package cr0s.warpdrive.data;
import net.minecraft.block.state.IBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
public class UnlistedPropertyBlockState implements IUnlistedProperty<IBlockState> {
private final String name;
UnlistedPropertyBlockState(final String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public boolean isValid(IBlockState value) {
return true;
}
@Override
public Class<IBlockState> getType() {
return IBlockState.class;
}
@Override
public String valueToString(IBlockState value) {
return value.toString();
}
}

View file

@ -0,0 +1,40 @@
package cr0s.warpdrive.event;
import cr0s.warpdrive.render.BakedModelCamouflage;
import java.util.ArrayList;
import java.util.Collection;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class ModelBakeEventHandler {
public static final ModelBakeEventHandler instance = new ModelBakeEventHandler();
private static final Collection<ModelResourceLocation> modelResourceLocationCamouflages = new ArrayList<>(64);
private ModelBakeEventHandler() {
}
public static void registerCamouflage(final ModelResourceLocation modelResourceLocation) {
modelResourceLocationCamouflages.add(modelResourceLocation);
}
// Called after all the other baked block models have been added to the modelRegistry, before BlockModelShapes caches the models.
@SubscribeEvent
public void onModelBake(ModelBakeEvent event) {
// add a camouflage wrapper around automatically registered models (from JSON)
for (final ModelResourceLocation modelResourceLocation : modelResourceLocationCamouflages) {
final Object object = event.getModelRegistry().getObject(modelResourceLocation);
if (object != null) {
final IBakedModel bakedModelExisting = (IBakedModel) object;
final BakedModelCamouflage bakedModelCamouflage = new BakedModelCamouflage(bakedModelExisting);
event.getModelRegistry().putObject(modelResourceLocation, bakedModelCamouflage);
}
}
}
}

View file

@ -0,0 +1,107 @@
package cr0s.warpdrive.render;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.data.BlockProperties;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
import java.util.List;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelShapes;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.block.model.ItemTransformVec3f;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.common.property.IExtendedBlockState;
public class BakedModelCamouflage implements IPerspectiveAwareModel {
private IBakedModel bakedModelDefault;
public BakedModelCamouflage(IBakedModel bakedModelDefault) {
this.bakedModelDefault = bakedModelDefault;
}
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable IBlockState blockState, @Nullable EnumFacing facing, long rand) {
if (blockState instanceof IExtendedBlockState) {
final IExtendedBlockState extendedBlockState = (IExtendedBlockState) blockState;
final IBlockState blockStateReference = extendedBlockState.getValue(BlockProperties.CAMOUFLAGE);
if (blockStateReference != Blocks.AIR.getDefaultState()) {
try {
// Retrieve the IBakedModel of the copied block and return it.
final BlockModelShapes blockModelShapes = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes();
final IBakedModel bakedModelResult = blockModelShapes.getModelForState(blockStateReference);
return bakedModelResult.getQuads(blockStateReference, facing, rand);
} catch(Exception exception) {
exception.printStackTrace();
WarpDrive.logger.error(String.format("Failed to render camouflage for block state %s, updating dictionary with %s = NOCAMOUFLAGE dictionary to prevent further errors",
blockStateReference,
blockStateReference.getBlock().getRegistryName()));
Dictionary.BLOCKS_NOCAMOUFLAGE.add(blockStateReference.getBlock());
}
}
}
return bakedModelDefault.getQuads(blockState, facing, rand);
}
@Nonnull
@Override
public TextureAtlasSprite getParticleTexture() {
return bakedModelDefault.getParticleTexture();
}
@Override
public boolean isAmbientOcclusion() {
return bakedModelDefault.isAmbientOcclusion();
}
@Override
public boolean isGui3d() {
return bakedModelDefault.isGui3d();
}
@Override
public boolean isBuiltInRenderer() {
return bakedModelDefault.isBuiltInRenderer();
}
@Nonnull
@Override
public ItemOverrideList getOverrides() {
return bakedModelDefault.getOverrides();
}
@Nonnull
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return bakedModelDefault.getItemCameraTransforms();
}
@Override
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) {
final Matrix4f matrix4f;
if (bakedModelDefault instanceof IPerspectiveAwareModel) {
matrix4f = ((IPerspectiveAwareModel) bakedModelDefault).handlePerspective(cameraTransformType).getRight();
} else {
final ItemTransformVec3f itemTransformVec3f = bakedModelDefault.getItemCameraTransforms().getTransform(cameraTransformType);
matrix4f = new TRSRTransformation(itemTransformVec3f).getMatrix();
}
return Pair.of(this, matrix4f);
}
}

View file

@ -1,58 +0,0 @@
package cr0s.warpdrive.render;
public class RenderBlockForceField {
}
/* @TODO MC1.10
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.block.forcefield.TileEntityForceField;
import cr0s.warpdrive.config.Dictionary;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockAccess;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
// wrapper to camouflage block
public class RenderBlockForceField implements ISimpleBlockRenderingHandler {
public static int renderId = 0;
public static RenderBlockForceField instance = new RenderBlockForceField();
@Override
public void renderInventoryBlock(Block block, int metadata, int modelId, RenderBlocks renderer) {
// this is not supposed to happen
//noinspection ConstantConditions
assert(false);
}
@Override
public boolean renderWorldBlock(IBlockAccess blockAccess, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
final TileEntity tileEntity = blockAccess.getTileEntity(x, y, z);
if (!(tileEntity instanceof TileEntityForceField)) {
return false;
}
int renderType = -1;
Block blockCamouflage = ((TileEntityForceField) tileEntity).cache_blockCamouflage;
if (blockCamouflage != null && !Dictionary.BLOCKS_NOCAMOUFLAGE.contains(blockCamouflage)) {
renderType = blockCamouflage.getRenderType();
}
return RenderCommons.renderWorldBlockCamouflaged(x, y, z, block, renderer, renderType, blockCamouflage);
}
@Override
public boolean shouldRender3DInInventory(int modelId) {
return true;
}
@Override
public int getRenderId() {
return renderId;
}
}
/**/