Skip to content

Instantly share code, notes, and snippets.

@StillManic
Last active January 9, 2016 02:08
Show Gist options
  • Save StillManic/01aad92fe2c5e0fb4bdd to your computer and use it in GitHub Desktop.
Save StillManic/01aad92fe2c5e0fb4bdd to your computer and use it in GitHub Desktop.
public static class OBJClock extends Block
{
public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
public static final PropertyBool TWENTY_FOUR = PropertyBool.create("twenty_four");
public static final PropertyBool SECONDARY = PropertyBool.create("secondary");
public static final OBJClock instance = new OBJClock();
public static final String name = "OBJClock";
private ExtendedBlockState state = new ExtendedBlockState(this, new IProperty[] {FACING, TWENTY_FOUR, SECONDARY}, new IUnlistedProperty[] {OBJModel.OBJProperty.instance});
// private String[] configNames = new String[] {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
// private int config = 0;
public OBJClock()
{
super(Material.iron);
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(TWENTY_FOUR, false).withProperty(SECONDARY, false));
setCreativeTab(CreativeTabs.tabBlock);
setUnlocalizedName(MODID + ":" + name);
}
@Override
public boolean isOpaqueCube() { return false; }
@Override
public boolean isFullCube() { return false; }
@Override
public boolean isVisuallyOpaque() { return false; }
@Override
public boolean hasTileEntity(IBlockState state)
{
return !state.getValue(SECONDARY);
}
@Override
public TileEntity createTileEntity(World world, IBlockState state)
{
return new OBJClockTileEntity(world, state.getValue(FACING));
}
private AxisAlignedBB getBounds(EnumFacing facing)
{
switch (facing)
{
case NORTH: return new AxisAlignedBB(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0625f);
case SOUTH: return new AxisAlignedBB(0.0f, 0.0f, 0.9375f, 1.0f, 1.0f, 1.0f);
case WEST: return new AxisAlignedBB(0.0f, 0.0f, 0.0f, 0.0625f, 1.0f, 1.0f);
case EAST: return new AxisAlignedBB(0.9375f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
default: return new AxisAlignedBB(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
}
}
@Override
public void setBlockBoundsBasedOnState(IBlockAccess world, BlockPos pos)
{
AxisAlignedBB box = this.getBounds(world.getBlockState(pos).getValue(FACING));
setBlockBounds((float) box.minX, (float) box.minY, (float) box.minZ, (float) box.maxX, (float) box.maxY, (float) box.maxZ);
}
@Override
public AxisAlignedBB getCollisionBoundingBox(World world, BlockPos pos, IBlockState state)
{
return null;
}
@Override
public void onNeighborBlockChange(World world, BlockPos pos, IBlockState state, Block neighbor)
{
if (neighbor != this && !world.isSideSolid(pos.offset(state.getValue(FACING)), state.getValue(FACING).getOpposite()))
{
this.breakBlock(world, pos, state);
}
}
@Override
public boolean canPlaceBlockOnSide(World world, BlockPos pos, EnumFacing side)
{
if (side.getAxis() == EnumFacing.Axis.Y) return false;
boolean canPlaceSelf = world.isSideSolid(pos.offset(side.getOpposite()), side);
boolean canPlaceNeighbor =
(this.canPlaceBlockAt(world, pos.offset(side.rotateY())) && world.isSideSolid(pos.offset(side.rotateY()).offset(side.getOpposite()), side)) ||
(this.canPlaceBlockAt(world, pos.offset(side.rotateYCCW())) && world.isSideSolid(pos.offset(side.rotateYCCW()).offset(side.getOpposite()), side));
return canPlaceSelf && canPlaceNeighbor;
}
@Override
public IBlockState onBlockPlaced(World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
{
IBlockState retState = this.getDefaultState().withProperty(TWENTY_FOUR, placer.isSneaking());
if (this.canPlaceBlockOnSide(world, pos, side))
{
retState = retState.withProperty(FACING, side.getOpposite());
BlockPos right = pos.offset(side.rotateY());
BlockPos left = pos.offset(side.rotateYCCW());
if (this.canPlaceBlockAt(world, pos) && this.canPlaceBlockAt(world, left) && this.canPlaceBlockOnSide(world, left, side))
{
retState = retState.withProperty(SECONDARY, false);
IBlockState secState = this.getDefaultState().withProperty(FACING, side.getOpposite()).withProperty(TWENTY_FOUR, placer.isSneaking()).withProperty(SECONDARY, true);
world.setBlockState(left, secState, 3);
}
else if (this.canPlaceBlockAt(world, pos) && this.canPlaceBlockAt(world, right) && this.canPlaceBlockOnSide(world, right, side))
{
retState = retState.withProperty(SECONDARY, true);
IBlockState primeState = this.getDefaultState().withProperty(FACING, side.getOpposite()).withProperty(TWENTY_FOUR, placer.isSneaking()).withProperty(SECONDARY, false);
world.setBlockState(right, primeState, 3);
}
}
return retState;
}
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
BlockPos tilePos = !state.getValue(SECONDARY) ? pos.offset(state.getValue(FACING).rotateYCCW()) : pos;
if (world.getTileEntity(tilePos) != null && world.getTileEntity(tilePos) instanceof OBJClockTileEntity)
{
((OBJClockTileEntity) world.getTileEntity(tilePos)).facing = state.getValue(FACING);
world.setBlockState(tilePos, state.withProperty(TWENTY_FOUR, ((OBJClockTileEntity) world.getTileEntity(tilePos)).isTwentyFour), 3);
}
}
@Override
public void breakBlock(World world, BlockPos pos, IBlockState state)
{
if (state.getValue(SECONDARY))
{
world.setBlockToAir(pos.offset(state.getValue(FACING).rotateYCCW()));
world.removeTileEntity(pos.offset(state.getValue(FACING).rotateYCCW()));
super.breakBlock(world, pos, state);
}
else
{
world.setBlockToAir(pos.offset(state.getValue(FACING).rotateY()));
super.breakBlock(world, pos, state);
}
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitz)
{
state = state.cycleProperty(TWENTY_FOUR);
world.setBlockState(pos, state, 3);
if (state.getValue(SECONDARY))
{
BlockPos primary = pos.offset(state.getValue(FACING).rotateYCCW());
world.setBlockState(primary, state.cycleProperty(SECONDARY), 3);
if (world.getTileEntity(primary) != null && world.getTileEntity(primary) instanceof OBJClockTileEntity)
{
((OBJClockTileEntity) world.getTileEntity(primary)).isTwentyFour = state.getValue(TWENTY_FOUR);
((OBJClockTileEntity) world.getTileEntity(primary)).facing = state.getValue(FACING);
}
}
else
{
world.setBlockState(pos.offset(state.getValue(FACING).rotateY()), state.cycleProperty(SECONDARY), 3);
if (world.getTileEntity(pos) != null && world.getTileEntity(pos) instanceof OBJClockTileEntity)
{
((OBJClockTileEntity) world.getTileEntity(pos)).isTwentyFour = state.getValue(TWENTY_FOUR);
((OBJClockTileEntity) world.getTileEntity(pos)).facing = state.getValue(FACING);
}
}
return true;
}
@Override
public IBlockState getStateFromMeta(int meta)
{
return this.getDefaultState().withProperty(FACING, EnumFacing.getHorizontal(meta & 3)).withProperty(TWENTY_FOUR, (meta & 4) > 0).withProperty(SECONDARY, (meta & 8) > 0);
}
@Override
public int getMetaFromState(IBlockState state)
{
int meta = 0;
if (state.getValue(SECONDARY)) meta |= 8;
if (state.getValue(TWENTY_FOUR)) meta |= 4;
meta |= state.getValue(FACING).getHorizontalIndex();
return meta;
}
@Override
public BlockState createBlockState()
{
return new ExtendedBlockState(this, new IProperty[] {FACING, TWENTY_FOUR, SECONDARY}, new IUnlistedProperty[] {OBJModel.OBJProperty.instance});
}
@Override
public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos)
{
OBJModel.OBJState retState = new OBJModel.OBJState(new TRSRTransformation(state.getValue(FACING)));
if (state.getValue(SECONDARY)) retState.setHideAllConfigs();
return ((IExtendedBlockState) this.state.getBaseState()).withProperty(OBJModel.OBJProperty.instance, retState);
}
}
{
"forge_marker": 1,
"defaults": {
"textures": {},
"model": "forgedebugmodelloaderregistry:clock_base.obj",
"custom": {
"gui3d": false
}
},
"variants": {
"inventory": [{
"transform": {
"firstperson": {
"translation": [0, 0.15, 0],
"rotation": [{"x": 0}, {"y": -45}, {"z": 0}]
},
"thirdperson": {
"translation": [0.06, 0, -0.15],
"rotation": {"x": 90},
"scale": 0.25
},
"gui": {
"translation": [-0.125, 0, 0],
"scale": 0.5
}
}
}],
"facing": {
"north": {},
"south": {"y": 180},
"west": {"y": 270},
"east": {"y": 90}
},
"twenty_four": {
"true": {},
"false": {}
},
"secondary": {
"true": {},
"false": {}
}
}
}
public static class OBJClockRender extends TileEntitySpecialRenderer<OBJClockTileEntity>
{
private static Map<String, IFlexibleBakedModel> loadedModels = Maps.newHashMap();
private static final ResourceLocation DIGIT = new ResourceLocation(MODID.toLowerCase() + ":block/clock_digit.obj");
public static void init()
{
IResourceManager manager = Minecraft.getMinecraft().getResourceManager();
if (manager instanceof IReloadableResourceManager)
{
((IReloadableResourceManager) manager).registerReloadListener(new IResourceManagerReloadListener()
{
@Override
public void onResourceManagerReload(IResourceManager ignored)
{
loadedModels.clear();
}
});
}
}
@Override
public void renderTileEntityAt(OBJClockTileEntity te, double x, double y, double z, float partialTicks, int destroyStage)
{
if (loadedModels.isEmpty())
{
FMLLog.info("loadedModels was empty, attempting to load model '%s'", DIGIT.toString());
TextureMap texMap = Minecraft.getMinecraft().getTextureMapBlocks();
IModel model = null;
try
{
model = ModelLoaderRegistry.getModel(DIGIT);
}
catch (IOException e)
{
FMLLog.severe("OBJClockRender: Failed to get model '%s' from ModelLoaderRegistry.", DIGIT);
}
if (model != null && model instanceof OBJModel)
{
FMLLog.info("Successfully obtained model from registry");
OBJModel objModel = new OBJModel(((OBJModel) model).getMatLib(), ((OBJModel) model).getModelLocation(), ((OBJModel) model).getCustomData());
OBJCustomData.GroupConfigHandler configHandler = objModel.getCustomData().getConfigHandler();
OBJCustomData.GroupConfigBuilder builder = configHandler.getConfigBuilder();
for (int i = 0; i <= 9; i++)
{
Pair<String, String[]> configOperation = te.getConfigOperationFor(i);
builder.startNew("" + i);
if (configOperation.getLeft().equals("hide")) builder.showAll(configOperation.getRight());
if (configOperation.getLeft().equals("show")) builder.hideAll(configOperation.getRight());
configHandler.addConfig(builder.build());
}
Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter = new Function<ResourceLocation, TextureAtlasSprite>()
{
@Nullable
@Override
public TextureAtlasSprite apply(@Nullable ResourceLocation location)
{
return location == null ? null : texMap.getAtlasSprite(location.toString());
}
};
for (int i = 0; i <= 9; i++)
{
OBJModel.OBJState state = new OBJModel.OBJState(Lists.newArrayList("" + i));
IFlexibleBakedModel baked = objModel.bake(state, Attributes.DEFAULT_BAKED_FORMAT, bakedTextureGetter);
loadedModels.put("" + i, baked);
}
}
}
IFlexibleBakedModel hourTens = null;
IFlexibleBakedModel hourOnes = null;
IFlexibleBakedModel minsTens = null;
IFlexibleBakedModel minsOnes = null;
int hour12 = Calendar.getInstance().get(Calendar.HOUR);
int hour24 = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
int minute = Calendar.getInstance().get(Calendar.MINUTE);
if (te.isTwentyFour)
{
String h24 = Integer.toString(hour24);
hourTens = h24.length() > 1 ? loadedModels.get("" + h24.charAt(0)) : null;
hourOnes = h24.length() > 1 ? loadedModels.get("" + h24.charAt(1)) : loadedModels.get("" + h24.charAt(0));
}
else
{
String h12 = Integer.toString(hour12);
if (hour12 == 0) h12 = "12";
hourTens = h12.length() > 1 ? loadedModels.get("" + h12.charAt(0)) : null;
hourOnes = h12.length() > 1 ? loadedModels.get("" + h12.charAt(1)) : loadedModels.get("" + h12.charAt(0));
}
String m = Integer.toString(minute);
minsTens = m.length() > 1 ? loadedModels.get("" + m.charAt(0)) : loadedModels.get("0");
minsOnes = m.length() > 1 ? loadedModels.get("" + m.charAt(1)) : loadedModels.get("" + m.charAt(0));
bindTexture(TextureMap.locationBlocksTexture);
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer worldRenderer = tessellator.getWorldRenderer();
GlStateManager.disableLighting();
GlStateManager.disableAlpha();
GlStateManager.disableRescaleNormal();
GlStateManager.enableDepth();
GlStateManager.depthMask(true);
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.pushMatrix();
GlStateManager.translate(x, y, z);
GlStateManager.pushMatrix();
GlStateManager.translate(0.5f, 0.5f, 0.5f);
switch (te.facing)
{
default:
case NORTH: break;
case SOUTH: GlStateManager.rotate(180, 0, 1, 0); break;
case WEST: GlStateManager.rotate(90, 0, 1, 0); break;
case EAST: GlStateManager.rotate(270, 0, 1, 0); break;
}
GlStateManager.translate(-0.5f, -0.5f, -0.5f);
if (hourTens != null)
{
worldRenderer.begin(GL11.GL_QUADS, Attributes.DEFAULT_BAKED_FORMAT);
for (BakedQuad quad : hourTens.getGeneralQuads())
{
LightUtil.renderQuadColor(worldRenderer, quad, 0xFFFFFFFF); //last argument is abgr!
}
tessellator.draw();
}
worldRenderer.begin(GL11.GL_QUADS, Attributes.DEFAULT_BAKED_FORMAT);
GlStateManager.translate(0.375f, 0.0f, 0.0f);
for (BakedQuad quad : hourOnes.getGeneralQuads())
{
LightUtil.renderQuadColor(worldRenderer, quad, 0xFFFFFFFF);
}
tessellator.draw();
if (minsTens != null)
{
worldRenderer.begin(GL11.GL_QUADS, Attributes.DEFAULT_BAKED_FORMAT);
GlStateManager.translate(0.497442f, 0.0f, 0.0f);
for (BakedQuad quad : minsTens.getGeneralQuads())
{
LightUtil.renderQuadColor(worldRenderer, quad, 0xFFFFFFFF);
}
tessellator.draw();
}
worldRenderer.begin(GL11.GL_QUADS, Attributes.DEFAULT_BAKED_FORMAT);
GlStateManager.translate(0.375f, 0.0f, 0.0f);
for (BakedQuad quad : minsOnes.getGeneralQuads())
{
LightUtil.renderQuadColor(worldRenderer, quad, 0xFFFFFFFF);
}
tessellator.draw();
GlStateManager.popMatrix();
GlStateManager.popMatrix();
}
}
public static class OBJClockTileEntity extends TileEntity
{
private boolean isTwentyFour = false;
private EnumFacing facing = EnumFacing.NORTH;
public OBJClockTileEntity() {}
public OBJClockTileEntity(World world, EnumFacing facing)
{
this.worldObj = world;
this.facing = facing;
}
public Pair<String, String[]> getConfigOperationFor(int index)
{
switch(index)
{
case 0: return Pair.of("hide", new String[] {"G"});
case 1: return Pair.of("show", new String[] {"E", "F"});
case 2: return Pair.of("hide", new String[] {"B", "E"});
case 3: return Pair.of("hide", new String[] {"B", "C"});
case 4: return Pair.of("hide", new String[] {"A", "C", "D"});
case 5: return Pair.of("hide", new String[] {"C", "F"});
case 6: return Pair.of("hide", new String[] {"F"});
case 7: return Pair.of("show", new String[] {"A", "E", "F"});
case 8: return Pair.of("hide", new String[] {});
case 9: return Pair.of("hide", new String[] {"C"});
default: return null;
}
}
@Override
public void writeToNBT(NBTTagCompound compound)
{
super.writeToNBT(compound);
compound.setBoolean("twenty_four", this.isTwentyFour);
compound.setInteger("facing", this.facing.getIndex());
}
@Override
public void readFromNBT(NBTTagCompound compound)
{
super.readFromNBT(compound);
if (compound.hasKey("twenty_four")) this.isTwentyFour = compound.getBoolean("twenty_four");
if (compound.hasKey("facing")) this.facing = EnumFacing.getFront(compound.getInteger("facing"));
}
@Override
public boolean shouldRenderInPass(int pass)
{
return pass == 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment