SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Digital Clock in Minecraft

Tue Feb 12, 2013 3:18 pm

I was very pleased to see Mojang release the Pi Edition of Minecraft. Its one of my favourite games, and now I can hack it with Python.

As Mojang themselves say they are giving us a voxel rendering engine to play with. I have used it to whip up a quick digital clock.
Image
Image

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Tue Feb 12, 2013 3:39 pm

Here is the Python code.
First of all here is a simple version that just redraws the whole clock every time. This can be fun if you make it out of block.SAND instead of block.ICE! Its also fun if you lower it a bit in a watery area.

Code: Select all

#! /usr/bin/python
import mcpi.block as block
import mcpi.minecraft as minecraft
import time

"""
Dot matrix digits 5x8 matrix.
0 - voxel should be drawn
Anything else - voxel should be cleared
"""
digit_dots = {
	'0':[
' 000',
'0   0',
'0   0',
'0   0',
'0   0',
'0   0',
'0   0',
' 000',
],
	'1':[
'  0',
' 00',
'  0',
'  0',
'  0',
'  0',
'  0',
' 000',
],
	'2':[
' 000',
'0   0',
'   0',
'  0',
' 0',
'0',
'0',
'00000',
],
	'3':[
' 000',
'0   0',
'    0',
'  00',
'    0',
'    0',
'0   0',
' 000',
],
	'4':[
'   0',
'  00',
' 0 0',
'0  0',
'00000',
'   0',
'   0',
'   0',
],
	'5':[
'00000',
'0',
'0',
'0000',
'    0',
'    0',
'0   0',
' 000',
],
	'6':[
' 000',
'0   0',
'0',
'0000',
'0   0',
'0   0',
'0   0',
' 000',
],
	'7':[
'00000',
'    0',
'   0',
'  0',
' 0',
'0',
'0',
'0',
],
	'8':[
' 000',
'0   0',
'0   0',
' 000',
'0   0',
'0   0',
'0   0',
' 000',
],
	'9':[
' 000',
'0   0',
'0   0',
' 0000',
'    0',
'    0',
'0   0',
' 000',
],
	':':[
'',
'',
'  00',
'  00',
'',
'  00',
'  00',
'',
],
}

def output_digit(client, position, offset, dots):
	"""
	Draw a digit in voxels.
	Client is the Minecraft connection.
	Position is the anchor point in Minecraft, a minecraft.Vec3.
	Offset is the number of the digit being drawn, starting at zero.
	Dots is an array of strings representing a digit.
	"""
	x_offset = offset * 6 # Each digit is 5 voxels wide, plus 1 for a gap between digits.
	line_offset = 0 # Start at the top line.
	for line in dots: # For each line of each digit.
		dot_offset = 0 # Start at the left-most voxel.
		for dot in line: # For each voxel in the line.
			if dot == '0': # If voxel should be drawn.
				client.setBlock(position.x+dot_offset+x_offset, position.y-line_offset, position.z, block.ICE)
			else: # Voxel should be cleared.
				client.setBlock(position.x+dot_offset+x_offset, position.y-line_offset, position.z, block.AIR)
			dot_offset += 1 # Move over to the next voxel.

		# Each digit is 5 wide, but not all 5 voxels need to be supplied in the digit_dots, so blank out any that were not given.
		for blank in range(dot_offset, 5):
			client.setBlock(position.x+blank+x_offset, position.y-line_offset, position.z, block.AIR)
		line_offset += 1 # Next line.

client=minecraft.Minecraft.create() # Connect to Minecraft.
place=client.player.getPos() # Start near the player.
place.y += 9 # Above the player's ground level.

while True: # Repeat forever.
	timestr = time.strftime("%H:%M:%S") # Format time nicely.
	digit_offset = 0 # Start with the first digit.
	for letter in timestr: # For each symbol in the time.
		map = digit_dots[letter] # Get the dot map for the current digit.
		output_digit(client, place, digit_offset, map) # Draw the digit.
		digit_offset += 1 # Next digit.
	time.sleep(0.5) # Rest a while before drawing again.

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Tue Feb 12, 2013 3:44 pm

And here is some more advanced code.
That last clock spends too much time redrawing parts of the time that has not changed. This version first draws the clock in a buffer and then only sends the changes to Minecraft.
As a result, the clock does not skip seconds and the CPU load is lower. However, if the player chips away some of the clock it might take a while to be redrawn, if ever.

Code: Select all

#! /usr/bin/python
import mcpi.block as block
import mcpi.minecraft as minecraft
import time

"""
Dot matrix digits 5 wide by 8 high.
0 - voxel should be drawn
Anything else - voxel should be cleared
"""
digit_dots = {
	'0':[
' 000',
'0   0',
'0   0',
'0   0',
'0   0',
'0   0',
'0   0',
' 000',
],
	'1':[
'  0',
' 00',
'  0',
'  0',
'  0',
'  0',
'  0',
' 000',
],
	'2':[
' 000',
'0   0',
'   0',
'  0',
' 0',
'0',
'0',
'00000',
],
	'3':[
' 000',
'0   0',
'    0',
'  00',
'    0',
'    0',
'0   0',
' 000',
],
	'4':[
'   0',
'  00',
' 0 0',
'0  0',
'00000',
'   0',
'   0',
'   0',
],
	'5':[
'00000',
'0',
'0',
'0000',
'    0',
'    0',
'0   0',
' 000',
],
	'6':[
' 000',
'0   0',
'0',
'0000',
'0   0',
'0   0',
'0   0',
' 000',
],
	'7':[
'00000',
'    0',
'   0',
'  0',
' 0',
'0',
'0',
'0',
],
	'8':[
' 000',
'0   0',
'0   0',
' 000',
'0   0',
'0   0',
'0   0',
' 000',
],
	'9':[
' 000',
'0   0',
'0   0',
' 0000',
'    0',
'    0',
'0   0',
' 000',
],
	':':[
'',
'',
'  00',
'  00',
'',
'  00',
'  00',
'',
],
}

class buffer:
	"""
	Double-buffer a voxel message for Minecraft.
	To improve performance, only changes are rendered.
	"""
	anchor_position = minecraft.Vec3(0,0,0)
	last_message = ''
	offscreen = []
	onscreen = []

	def __init__(self, anchor_position):
		"""
		Set everything up to render messages into the world
		at the given position.
		"""
		self.anchor_position = anchor_position

	def render(self, message):
		"""
		Put message into the off-screen buffer.
		"""
		if message != self.last_message: # Do nothing if the message has not changed.
			self.last_message =  message # For next time.

			self.offscreen = [] # Clear any previous use of the buffer.
			letter_offset = 0
			for letter in message:
				rendition = digit_dots[letter]
				line_offset = 0
				for line in rendition:
					if len(self.offscreen) <= line_offset:
						# Make space to store the drawing.
						self.offscreen.append([])
					dot_offset = 0
					for dot in line:
						if dot == '0':
							self.offscreen[line_offset].append(block.ICE)
						else:
							self.offscreen[line_offset].append(block.AIR)
						dot_offset += 1
					for blank in range(dot_offset, 6):
						# Expand short lines to the full width of 6 voxels.
						self.offscreen[line_offset].append(block.AIR)
					line_offset += 1
				letter_offset += 1

			# Clear the onscreen buffer.
			# Should only happen on the first call.
			# Assumption: message will always be the same size.
			# Assumption: render() is called before flip().
			if self.onscreen == []:
				# No onscreen copy - so make it the same size as the offscreen image. Fill with AIR voxels.
				line_offset = 0
				for line in self.offscreen:
					self.onscreen.append([])
					for dot in line:
						self.onscreen[line_offset].append(block.AIR)
					line_offset += 1

	def flip(self, client):
		"""
		Put the off-screen buffer onto the screen.
		Only send the differences.
		Remember the new screen for next flip.
		"""
		line_offset = 0
		for line in self.offscreen:
			dot_offset = 0
			for dot in line:
				if self.onscreen[line_offset][dot_offset] != dot:
					self.onscreen[line_offset][dot_offset] = dot
					client.setBlock(self.anchor_position.x+dot_offset,self.anchor_position.y-line_offset,self.anchor_position.z, dot)
				dot_offset += 1
			line_offset += 1

client=minecraft.Minecraft.create() # Connect to Minecraft.
place=client.player.getPos() # Start near the player.
place.y += 9 # Above the player's ground level.
bitmapper = buffer(place)

while True:
	timestr = time.strftime("%H:%M:%S") # Format time nicely.
	bitmapper.render(timestr)
	bitmapper.flip(client)
	time.sleep(.1) # Rest a while before drawing again.

User avatar
spsn
Posts: 72
Joined: Wed Nov 07, 2012 6:33 pm

Re: Digital Clock in Minecraft

Tue Feb 12, 2013 9:54 pm

Very nice. Well done.

simplesi
Posts: 2327
Joined: Fri Feb 24, 2012 6:19 pm
Location: Euxton, Lancashire, UK

Re: Digital Clock in Minecraft

Tue Feb 12, 2013 10:14 pm

Wow - just Wow :)

Simon
Seeking help with Scratch and I/O stuff for Primary age children
http://cymplecy.wordpress.com/ @cymplecy on twitter

seankean
Posts: 1
Joined: Tue Feb 12, 2013 11:13 pm

Re: Digital Clock in Minecraft

Tue Feb 12, 2013 11:25 pm

Wow this is really interesting - just ordered a Rasberry Pi to test out Minecraft Pi Edition.

Is it possible to program lower level control of graphics rendering - or only 'in world' things like blocks?

I'm working to make a voxel based 3D display ( volumetric display = http://en.wikipedia.org/wiki/Volumetric_display ) and if its possible to access the way graphics are written to the screen its possible we could make it so that people could play pi minecraft on a sort of 'holographic' display.

any help with this would be appreciated on the pi/minecraft end - thanks

[email protected]

mcpipy
Posts: 5
Joined: Wed Feb 13, 2013 1:21 am

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 1:34 am

Very cool! I've started collecting all the python programs for MC Pi I can find and this is the most advanced one yet! Cataloged @ http://mcpipy.com

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 2:05 am

@seankean:
My code just adds and removes blocks in the Minecraft word. Minecraft itself is responsible for all the rendering.

Minecraft renders down to a 2D plane and is probably not suitable for driving a real 3D display.
The Raspberry Pi has a 2D framebuffer but you would want a 3D volumebuffer.
Having said that, representing the world as a coarse collection of large, low-resolution blocks would probably really help with your project. And Mojang themselves might be interested in porting Minecraft once you have your display working.

Note that the full version of Minecraft has an anaglyphic mode which can give a better illusion of depth.

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 2:20 am

I've done a little more playing with the digital clock concept. This version draws the clock horizontally rather than vertically, and it looks more like an LCD panel meter.
Image
Close view.
Image

User avatar
malakai
Posts: 1382
Joined: Sat Sep 15, 2012 10:35 am

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 2:22 am

Very nice thanks for showing your great work. Your bound to be very popular if you keep this going and please do.
http://www.raspians.com - always looking for content feel free to ask to have it posted. Or sign up and message me to become a contributor to the site. Raspians is not affiliated with the Raspberry Pi Foundation. (RPi's + You = Raspians)

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 2:39 am

Here is the adjust code for the panel meter.
The main changes are building a volume to house the display, and rendering the digits horizontally.
The panel is drawn under the player's feet so it might be a good idea to climb up on a couple of blocks first.

Code: Select all

#! /usr/bin/python
import mcpi.block as block
import mcpi.minecraft as minecraft
import time

"""
Dot matrix digits 5 wide by 8 high.
0 - voxel should be drawn
Anything else - voxel should be cleared
"""
digit_dots = {
	'0':[
' 000',
'0   0',
'0   0',
'0   0',
'0   0',
'0   0',
'0   0',
' 000',
],
	'1':[
'  0',
' 00',
'  0',
'  0',
'  0',
'  0',
'  0',
' 000',
],
	'2':[
' 000',
'0   0',
'   0',
'  0',
' 0',
'0',
'0',
'00000',
],
	'3':[
' 000',
'0   0',
'    0',
'  00',
'    0',
'    0',
'0   0',
' 000',
],
	'4':[
'   0',
'  00',
' 0 0',
'0  0',
'00000',
'   0',
'   0',
'   0',
],
	'5':[
'00000',
'0',
'0',
'0000',
'    0',
'    0',
'0   0',
' 000',
],
	'6':[
' 000',
'0   0',
'0',
'0000',
'0   0',
'0   0',
'0   0',
' 000',
],
	'7':[
'00000',
'    0',
'   0',
'  0',
' 0',
'0',
'0',
'0',
],
	'8':[
' 000',
'0   0',
'0   0',
' 000',
'0   0',
'0   0',
'0   0',
' 000',
],
	'9':[
' 000',
'0   0',
'0   0',
' 0000',
'    0',
'    0',
'0   0',
' 000',
],
	':':[
'',
'',
'  00',
'  00',
'',
'  00',
'  00',
'',
],
}

class buffer:
	"""
	Double-buffer a voxel message for Minecraft.
	To improve performance, only changes are rendered.
	"""
	anchor_position = minecraft.Vec3(0,0,0)
	last_message = ''
	offscreen = []
	onscreen = []
	unset = block.OBSIDIAN
	set = block.SNOW_BLOCK

	def __init__(self, anchor_position):
		"""
		Set everything up to render messages into the world
		at the given position.
		"""
		self.anchor_position = anchor_position

	def draw_base(self, client):
		"""
		Build some foundations for the clock.
		"""
		# Foundations of stone.
		for y in range(-5, -1): # Nice thick base.
			for x in range(-1, 8*6): # 8 digits each 6 wide, plus a border, minus one to cut out the space beside the last digit.
				for z in range(-1, 8+1): # Each digit is 8 high, plus a border.
					client.setBlock(self.anchor_position.x+x, self.anchor_position.y+y, self.anchor_position.z+z, block.STONE)
		# Shallow pool at the top.
		for x in range(0, 8*6-1):
			for z in range(0, 8):
				client.setBlock(self.anchor_position.x+x, self.anchor_position.y-2, self.anchor_position.z+z, block.WATER)

	def render(self, message):
		"""
		Put message into the off-screen buffer.
		"""
		if message != self.last_message: # Do nothing if the message has not changed.
			self.last_message =  message # For next time.

			self.offscreen = [] # Clear any previous use of the buffer.
			letter_offset = 0
			for letter in message:
				rendition = digit_dots[letter]
				line_offset = 0
				for line in rendition:
					if len(self.offscreen) <= line_offset:
						# Make space to store the drawing.
						self.offscreen.append([])
					dot_offset = 0
					for dot in line:
						if dot == '0':
							self.offscreen[line_offset].append(self.set)
						else:
							self.offscreen[line_offset].append(self.unset)
						dot_offset += 1
					for blank in range(dot_offset, 6):
						# Expand short lines to the full width of 6 voxels.
						self.offscreen[line_offset].append(self.unset)
					line_offset += 1
				letter_offset += 1

			# Clear the onscreen buffer.
			# Should only happen on the first call.
			# Assumption: message will always be the same size.
			# Assumption: render() is called before flip().
			if self.onscreen == []:
				# No onscreen copy yet - so make it the same size as the offscreen image. Fill with suitable voxels.
				line_offset = 0
				for line in self.offscreen:
					self.onscreen.append([])
					for dot in line:
						self.onscreen[line_offset].append(block.DIRT)
					line_offset += 1

	def flip(self, client):
		"""
		Put the off-screen buffer onto the screen.
		Only send the differences.
		Remember the new screen for next flip.
		Draw the clock inverted so it read properly from above.
		"""
		line_offset = 0
		height = len(self.offscreen) - 1
		for line in self.offscreen:
			dot_offset = 0
			length = len(line) - 2 # Fit into the border better.
			for dot in line:
				if self.onscreen[line_offset][dot_offset] != dot:
					self.onscreen[line_offset][dot_offset] = dot
					client.setBlock(self.anchor_position.x+length-dot_offset, self.anchor_position.y-3, self.anchor_position.z+height-line_offset, dot)
				dot_offset += 1
			line_offset += 1

client=minecraft.Minecraft.create() # Connect to Minecraft.
place=client.player.getPos() # Start near the player.
# place.y is just below the player, and we don't need to change it.
bitmapper = buffer(place)

bitmapper.draw_base(client)
while True:
	timestr = time.strftime("%H:%M:%S") # Format time nicely.
	bitmapper.render(timestr)
	bitmapper.flip(client)
	time.sleep(.1) # Rest a while before drawing again.

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 9:22 am

Just for fun I have moved on to a real-time analogue clock now.
Image
I'd say that this one is "interestingly ugly". The still picture does not do it justice. I'll post a video later if I can work out how.
Yes, its just a few seconds after 7:00.

For this project I use PIL (Python Imaging Library) to draw lines and circles. I draw the clock at higher resolution then reduce it for display. It really opens your eyes to the problems that people who draw icons have with limited resolution.

The approach used here could be used for displaying real-world graphs in Minecraft.

Code: Select all

#! /usr/bin/python
"""
Draw an analogue clock into Minecraft.
Use PIL to prepare the bitmaps, then update Minecraft.

SleepyOz: tfptfp(at)gmail.com
2013-02-13
"""

import math
import mcpi.block as block
import mcpi.minecraft as minecraft
from PIL import Image # Remember to "sudo apt-get install python-imaging" to make PIL available.
from PIL import ImageDraw
import time

# Not very good colour names, because they are inverting when displayed.
colour_black = 1
colour_dark = 32
colour_medium  = 64
colour_light = 128
colour_white = 192

def clockhand(angle, length):
	"""
	Calculate the end point for the given vector.
	Angle 0 is 12 o'clock, 90 is 3 o'clock.
	Based around (32,32) as origin, (0,0) in top left.
	"""
	radian_angle = math.pi * angle / 180.0
	x = 32 + length * math.cos(radian_angle)
	y = 32 + length * math.sin(radian_angle)
	return [(32,32),(x,y)]

def draw_clock():
	"""
	Draw an analogue clock face.
	In an attempt to improve appearance, the clock is drawn at a higher
	resolution then scaled down with anti-aliasing.
	"""
	now = time.localtime()

	bitmap = Image.new("L", (65,65), color=colour_black) # Work with oversized images, and reduce before displaying.
	draw = ImageDraw.Draw(bitmap) # An object to draw into.

	# Multiple outer rings so something survives the resolution reduction later.
	draw.ellipse((1,1,64,64), outline=colour_white) # Face.
	draw.ellipse((2,2,63,63), outline=colour_white) # Face.
	draw.ellipse((3,3,62,62), outline=colour_white) # Face.
	draw.ellipse((4,4,61,61), outline=colour_white) # Face.

	# TODO: We could draw numbers or chevrons on the clock face.

	# The hands are drawn by converting the time to degrees.
	# Note that all the hands move every second, althought the change might be too small to see.
	# The hour hand only moves every minute and even that is not visible.
	draw.line(clockhand(now.tm_hour * 30 + now.tm_min / 2, 20), fill=colour_white, width=4) # Hour hand.
	draw.line(clockhand(now.tm_min * 6 + now.tm_sec / 10, 22), fill=colour_white, width=3) # Minute hand.
	draw.line(clockhand(now.tm_sec * 6, 25), fill=colour_white, width=2) # Second hand.

	bitmap.thumbnail((32,32), Image.ANTIALIAS) # Reduce resolution to suit the view distance.
	return bitmap

class buffer:
	"""
	Double-buffer a voxel block for Minecraft.
	To improve performance, only changes are actually sent to Minecraft.
	"""
	anchor_position = minecraft.Vec3(0,0,0)
	offscreen = None
	onscreen = None

	def __init__(self, anchor_position):
		"""
		Set everything up to render the voxels into the world
		at the given position.
		"""
		self.anchor_position = anchor_position
		self.onscreen = Image.new("L", (32,32), color=0)

	def render(self):
		"""
		Get a picture of the clock.
		"""
		self.offscreen = draw_clock()

	def flip(self, client):
		"""
		Put the off-screen buffer onto the screen.
		Only send the differences.
		Remember the new screen for use during the next flip.
		"""
		if self.offscreen:
			width,height = self.offscreen.size
			draw = ImageDraw.Draw(self.onscreen) # So we can remember what we did for next time.
			for x in range(0, width - 1):
				for z in range(0, height - 1):
					dot = self.offscreen.getpixel((x,z))
					if self.onscreen.getpixel((x,z)) != dot:
						# Change detected.
						draw.point((x,z), fill=dot)

						# Pick display items that suit the antialiasing.
						display = block.SNOW_BLOCK # Very white.
						if (dot >= colour_dark+16) and (dot < colour_medium + 16):
							display = block.WOOL # Light grey.
						elif (dot >= colour_medium + 16) and (dot < colour_light + 16):
							display = block.STONE # Medium grey.
						elif (dot >= colour_light + 16):
							display = block.OBSIDIAN # Blackish.

						client.setBlock(self.anchor_position.x + x, self.anchor_position.y, self.anchor_position.z + z, display)

client=minecraft.Minecraft.create() # Connect to Minecraft.
place=client.player.getPos() # Start near the player.
place.y += 0 # At the level of the player's feet.
bitmapper = buffer(place)

while True:
	bitmapper.render()
	bitmapper.flip(client)
	time.sleep(.1) # Rest a while before drawing again.

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 10:51 am

Here's a video of the analogue clock ticking.
http://vimeo.com/59559050

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Wed Feb 13, 2013 10:56 am

Thanks for crossposting over there. Please also post the panel and analogue clock.
mcpipy wrote:Very cool! I've started collecting all the python programs for MC Pi I can find and this is the most advanced one yet! Cataloged @ http://mcpipy.com

mcpipy
Posts: 5
Joined: Wed Feb 13, 2013 1:21 am

Re: Digital Clock in Minecraft

Thu Feb 14, 2013 2:58 am

>> Thanks for crossposting over there. Please also post the panel and analogue clock.

Done, thanks for sharing your creations!!!

User avatar
LetHopeItsSnowing
Posts: 357
Joined: Sat May 26, 2012 6:40 am
Location: UK

Re: Digital Clock in Minecraft

Fri Feb 15, 2013 9:25 pm

Loving your work SleepyOz, digital clock is a particular master piece.

It gave me some inspiration to make my own analogue clock. I wanted to create one which was absolutely massive... big enough so I could walk on the arms.

This is what I came up with http://www.stuffaboutcode.com/2013/02/r ... clock.html

Martin
"am I getting slower, or is stuff more complicated; either way I now have to write it down - stuffaboutcode.com"

blakespot
Posts: 11
Joined: Fri Jul 06, 2012 9:22 pm

Re: Digital Clock in Minecraft

Mon Feb 18, 2013 10:46 pm

When I run this I get sporadic Drained Data: <Fail Fail Fail Fail Fail> messages. Nothing renders. Why would this be? Just grabbed latest Wheezy and Minecraft Pi. mcpi in same dir, etc.

Thanks. Trying to get into this / to get excited here. :-)

SleepyOz
Posts: 10
Joined: Tue Feb 12, 2013 2:44 pm

Re: Digital Clock in Minecraft

Wed Feb 27, 2013 10:42 am

blakespot wrote:When I run this I get sporadic Drained Data: <Fail Fail Fail Fail Fail> messages. Nothing renders. Why would this be? Just grabbed latest Wheezy and Minecraft Pi. mcpi in same dir, etc.

Thanks. Trying to get into this / to get excited here. :-)
I forgot to mention that I just wrote and ran these examples in the Minecraft directories. Specifically, I worked in

Code: Select all

mcpi/api/python

And you need to start Minecraft first, generate a new world and find a place to anchor the clock. All these examples create a clock near the player's feet so its good to start near the middle of the map.

matthewb42
Posts: 1
Joined: Thu Jan 04, 2018 6:04 am

Re: Digital Clock in Minecraft

Thu Jan 04, 2018 6:07 am

So I was just wondering. Does this have to be done in Python 2 or 3?

Thanks for any help. :)

Erics_Cixon__
Posts: 4
Joined: Mon Apr 13, 2020 9:25 pm

Re: Digital Clock in Minecraft

Mon Apr 13, 2020 9:27 pm

Here is my "Unaddicter":

Code: Select all

import mcpi.minecraft as minecraft
import mcpi.block as block
from datetime import datetime
from time import sleep
mc = minecraft.Minecraft.create()
D0 = [True, True, True, True, True, True, False]
D1 = [False, False, True, False, True, False, False]
D2 = [True, False, True, True, False, True, True]
D3 = [True, False, True, False, True, True, True]
D4 = [False, True, True, False, True, False, True]
D5 = [True, True, False, False, True, True, True]
D6 = [True, True, False, True, True, True, True]
D7 = [True, False, True, False, True, False, False]
D8 = [True, True, True, True, True, True, True]
D9 = [True, True, True, False, True, False, True]
A = [True, True, True, True, True, False, True]
P = [True, True, True, True, False, False, True]
M = [
    [False, True,  True,  False, True,  True,  False],
    [True,  False, False, True,  False, False, True],
    [True,  False, False, True,  False, False, True],
    [False, False, False, False, False, False, False],
    [True,  False, False, True,  False, False, True],
    [True,  False, False, True,  False, False, True],
    [False, False, False, False, False, False, False]
]
DS = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9]
BOUND = [7, 19]
FID = block.WOOL
FID.data = 5
TID = block.WOOL
TID.data = 14
yz = None
playerX = mc.player.getPos().x
playerY = mc.player.getPos().y
playerZ = mc.player.getPos().z
def GET_TIME():
    global yz
    yz = datetime.now()
    x = [yz.hour if yz.hour < 13 else yz.hour - 12, yz.minute, "AM" if yz.hour < 13 else "PM", yz.second, yz.microsecond // 100000] # x[3] and x[4] are just track dummies
    if x[0] == 12:
        x[2] = "AM" if x[2] == "PM" else "PM"
    return x
def GET_ZLIST_FROM_7SEG(_7seg):
    return [
        [False, _7seg[0], _7seg[0], False],
        [_7seg[1], False, False, _7seg[2]],
        [_7seg[1], False, False, _7seg[2]],
        [False, _7seg[6], _7seg[6], False],
        [_7seg[3], False, False, _7seg[4]],
        [_7seg[3], False, False, _7seg[4]],
        [False, _7seg[5], _7seg[5], False]
    ]
wLasttime = None
def DRAW_CLOCK():
    global wLasttime
    wtime = GET_TIME()
    if not (wLasttime == None or wLasttime == wtime):
        return
    wLasttime = wtime
    for y in range(playerY, playerY + 9):
        for z in range(playerZ, playerZ + 38):
            mc.setBlock(playerX + 1, y, z, FID)
            mc.setBlock(playerX + 2, y, z, FID)
    mc.setBlock(playerX + 1, playerY + 2, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 3, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 5, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 6, playerZ + 12, TID)
    if wtime[0] > 9:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[0])[0])])
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[0])[1])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 1, playerZ + 5):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 6, playerZ + 11):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
    else:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime)[0])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 6, playerZ + 11):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
    if wtime[1] > 9:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[1])[0])])
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[1])[1])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 14, playerZ + 18):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 19, playerZ + 23):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
    else:
        d0 = GET_ZLIST_FROM_7SEG(D0)
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime)[0])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 14, playerZ + 18):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 19, playerZ + 23):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
    dm = GET_ZLIST_FROM_7SEG(A if wtime[2] == "AM" else P)
    for y in range(playerY + 7, playerY, -1):
        for z in range(playerZ + 24, playerZ + 28):
            mc.setBlock(playerX + 1, y, z, TID if dm[y - playerY][z - playerZ] else FID)
    for y in range(playerY + 7, playerY, -1):
        for z in range(playerZ + 29, playerZ + 36):
            mc.setBlock(playerX + 1, y, z, TID if m[y - playerY][z - playerZ] else FID)
    if yz.hour < BOUND[0] or yz.hour > BOUND[1]:
        mc.setBlock(playerX + 1, playerY + 1, playerZ + 37, TID)
mc.postToChat("Unaddicter 1.0 by Eric Silveira")
while True:
    DRAW_CLOCK()

Erics_Cixon__
Posts: 4
Joined: Mon Apr 13, 2020 9:25 pm

Re: Digital Clock in Minecraft

Mon Apr 13, 2020 9:39 pm

Another bugfix

Code: Select all

import mcpi.minecraft as minecraft
import mcpi.block as block
from datetime import datetime
from time import sleep
mc = minecraft.Minecraft.create()
D0 = [True, True, True, True, True, True, False]
D1 = [False, False, True, False, True, False, False]
D2 = [True, False, True, True, False, True, True]
D3 = [True, False, True, False, True, True, True]
D4 = [False, True, True, False, True, False, True]
D5 = [True, True, False, False, True, True, True]
D6 = [True, True, False, True, True, True, True]
D7 = [True, False, True, False, True, False, False]
D8 = [True, True, True, True, True, True, True]
D9 = [True, True, True, False, True, False, True]
A = [True, True, True, True, True, False, True]
P = [True, True, True, True, False, False, True]
M = [
    [False, True,  True,  False, True,  True,  False],
    [True,  False, False, True,  False, False, True],
    [True,  False, False, True,  False, False, True],
    [False, False, False, False, False, False, False],
    [True,  False, False, True,  False, False, True],
    [True,  False, False, True,  False, False, True],
    [False, False, False, False, False, False, False]
]
DS = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9]
BOUND = [7, 19]
FID = block.WOOL
FID.data = 5
TID = block.WOOL
TID.data = 14
yz = None
playerX = int(mc.player.getPos().x)
playerY = int(mc.player.getPos().y)
playerZ = int(mc.player.getPos().z)
def GET_TIME():
    global yz
    yz = datetime.now()
    x = [yz.hour if yz.hour < 13 else yz.hour - 12, yz.minute, "AM" if yz.hour < 13 else "PM", yz.second, yz.microsecond // 100000] # x[3] and x[4] are just track dummies
    if x[0] == 12:
        x[2] = "AM" if x[2] == "PM" else "PM"
    return x
def GET_ZLIST_FROM_7SEG(_7seg):
    return [
        [False, _7seg[0], _7seg[0], False],
        [_7seg[1], False, False, _7seg[2]],
        [_7seg[1], False, False, _7seg[2]],
        [False, _7seg[6], _7seg[6], False],
        [_7seg[3], False, False, _7seg[4]],
        [_7seg[3], False, False, _7seg[4]],
        [False, _7seg[5], _7seg[5], False]
    ]
wLasttime = None
def DRAW_CLOCK():
    global wLasttime
    wtime = GET_TIME()
    if not (wLasttime == None or wLasttime == wtime):
        return
    wLasttime = wtime
    for y in range(playerY, playerY + 9):
        for z in range(playerZ, playerZ + 38):
            mc.setBlock(playerX + 1, y, z, FID)
            mc.setBlock(playerX + 2, y, z, FID)
    mc.setBlock(playerX + 1, playerY + 2, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 3, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 5, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 6, playerZ + 12, TID)
    if wtime[0] > 9:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[0])[0])])
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[0])[1])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 1, playerZ + 5):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 6, playerZ + 11):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
    else:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime)[0])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 6, playerZ + 11):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
    if wtime[1] > 9:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[1])[0])])
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[1])[1])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 14, playerZ + 18):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 19, playerZ + 23):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
    else:
        d0 = GET_ZLIST_FROM_7SEG(D0)
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime)[0])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 14, playerZ + 18):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 19, playerZ + 23):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
    dm = GET_ZLIST_FROM_7SEG(A if wtime[2] == "AM" else P)
    for y in range(playerY + 7, playerY, -1):
        for z in range(playerZ + 24, playerZ + 28):
            mc.setBlock(playerX + 1, y, z, TID if dm[y - playerY][z - playerZ] else FID)
    for y in range(playerY + 7, playerY, -1):
        for z in range(playerZ + 29, playerZ + 36):
            mc.setBlock(playerX + 1, y, z, TID if M[y - playerY][z - playerZ] else FID)
    if yz.hour < BOUND[0] or yz.hour > BOUND[1]:
        mc.setBlock(playerX + 1, playerY + 1, playerZ + 37, TID)
mc.postToChat("Unaddicter 1.0 by Eric Silveira")
while True:
    DRAW_CLOCK()

Erics_Cixon__
Posts: 4
Joined: Mon Apr 13, 2020 9:25 pm

Re: Digital Clock in Minecraft

Mon Apr 13, 2020 9:47 pm

Another bugfix - and a swap:

Code: Select all

import mcpi.minecraft as minecraft
import mcpi.block as block
from datetime import datetime
from time import sleep
mc = minecraft.Minecraft.create()
D0 = [True, True, True, True, True, True, False]
D1 = [False, False, True, False, True, False, False]
D2 = [True, False, True, True, False, True, True]
D3 = [True, False, True, False, True, True, True]
D4 = [False, True, True, False, True, False, True]
D5 = [True, True, False, False, True, True, True]
D6 = [True, True, False, True, True, True, True]
D7 = [True, False, True, False, True, False, False]
D8 = [True, True, True, True, True, True, True]
D9 = [True, True, True, False, True, False, True]
A = [True, True, True, True, True, False, True]
P = [True, True, True, True, False, False, True]
M = [
    [False, True,  True,  False, True,  True,  False],
    [True,  False, False, True,  False, False, True],
    [True,  False, False, True,  False, False, True],
    [False, False, False, False, False, False, False],
    [True,  False, False, True,  False, False, True],
    [True,  False, False, True,  False, False, True],
    [False, False, False, False, False, False, False]
]
DS = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9]
BOUND = [7, 19]
FID = block.WOOL
FID.data = 14
TID = block.WOOL
TID.data = 5
yz = None
playerX = int(mc.player.getPos().x)
playerY = int(mc.player.getPos().y)
playerZ = int(mc.player.getPos().z)
def GET_TIME():
    global yz
    yz = datetime.now()
    x = [yz.hour if yz.hour < 13 else yz.hour - 12, yz.minute, "AM" if yz.hour < 13 else "PM", yz.second, yz.microsecond // 100000] # x[3] and x[4] are just track dummies
    if x[0] == 12:
        x[2] = "AM" if x[2] == "PM" else "PM"
    return x
def GET_ZLIST_FROM_7SEG(_7seg):
    return [
        [False, _7seg[0], _7seg[0], False],
        [_7seg[1], False, False, _7seg[2]],
        [_7seg[1], False, False, _7seg[2]],
        [False, _7seg[6], _7seg[6], False],
        [_7seg[3], False, False, _7seg[4]],
        [_7seg[3], False, False, _7seg[4]],
        [False, _7seg[5], _7seg[5], False]
    ]
wLasttime = None
def DRAW_CLOCK():
    global wLasttime
    wtime = GET_TIME()
    if not (wLasttime == None or wLasttime == wtime):
        return
    wLasttime = wtime
    for y in range(playerY, playerY + 9):
        for z in range(playerZ, playerZ + 38):
            mc.setBlock(playerX + 1, y, z, FID)
            mc.setBlock(playerX + 2, y, z, FID)
    mc.setBlock(playerX + 1, playerY + 2, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 3, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 5, playerZ + 12, TID)
    mc.setBlock(playerX + 1, playerY + 6, playerZ + 12, TID)
    if wtime[0] > 9:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[0])[0])])
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[0])[1])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 1, playerZ + 5):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 6, playerZ + 11):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
    else:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime)[0])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 6, playerZ + 11):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
    if wtime[1] > 9:
        d0 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[1])[0])])
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[1])[1])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 14, playerZ + 18):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 19, playerZ + 23):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
    else:
        d0 = GET_ZLIST_FROM_7SEG(D0)
        d1 = GET_ZLIST_FROM_7SEG(DS[int(str(wtime[1])[0])])
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 14, playerZ + 18):
                mc.setBlock(playerX + 1, y, z, TID if d1[y - playerY][z - playerZ] else FID)
        for y in range(playerY + 7, playerY, -1):
            for z in range(playerZ + 19, playerZ + 23):
                mc.setBlock(playerX + 1, y, z, TID if d0[y - playerY][z - playerZ] else FID)
    dm = GET_ZLIST_FROM_7SEG(A if wtime[2] == "AM" else P)
    for y in range(playerY + 7, playerY, -1):
        for z in range(playerZ + 24, playerZ + 28):
            mc.setBlock(playerX + 1, y, z, TID if dm[y - playerY][z - playerZ] else FID)
    for y in range(playerY + 7, playerY, -1):
        for z in range(playerZ + 29, playerZ + 36):
            mc.setBlock(playerX + 1, y, z, TID if M[y - playerY][z - playerZ] else FID)
    if yz.hour < BOUND[0] or yz.hour > BOUND[1]:
        mc.setBlock(playerX + 1, playerY + 1, playerZ + 37, TID)
mc.postToChat("Unaddicter 1.0 by Eric Silveira")
while True:
    DRAW_CLOCK()

Erics_Cixon__
Posts: 4
Joined: Mon Apr 13, 2020 9:25 pm

Re: Digital Clock in Minecraft

Mon Apr 13, 2020 10:06 pm

Ugh. There is a bug I can't fix.

Return to “Python”