Last active
January 9, 2016 02:08
-
-
Save StillManic/01aad92fe2c5e0fb4bdd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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": {} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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