Skip to content
This repository was archived by the owner on Aug 31, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
217fcb9
Introduce a config parameter that makes kill
Jun 6, 2014
8d23b90
Fix typo in datautils.py
Jun 6, 2014
c45742a
Merge pull request #1 from nickelpro/patch-1
spalanzani Jun 6, 2014
41714cd
Stance (headY) field seems to have been in the wrong place.
Jun 7, 2014
0911c6c
1.7.6 protocol update
nickelpro Aug 16, 2014
8cb8fcb
Add all non-variant biomes
guineawheek Aug 20, 2014
7ee4b78
Update mapdata.py
guineawheek Aug 20, 2014
ff3bace
Added the rest of the biomes
guineawheek Aug 20, 2014
13dbd01
Merge pull request #24 from guineawheek/master
Aug 20, 2014
56f78f7
Update ReadMe.md
Aug 25, 2014
a508503
Merge remote-tracking branch 'refs/remotes/nickelpro-spock/master'
spalanzani Sep 27, 2014
6170c40
Reducing the world plugin’s memory footprint
spalanzani Oct 3, 2014
cc6a319
introducing replacing individual blocks in
spalanzani Oct 7, 2014
b279082
Big ol hunk of unfinished commit
nickelpro Oct 13, 2014
c4d5c5c
Merge branch 'master' of github.com:nickelpro/spock
nickelpro Oct 13, 2014
6a063f0
Better warn wayward travelers
nickelpro Oct 13, 2014
dc8cc51
Gross Syntax Error
nickelpro Oct 13, 2014
3c2227d
Another day, another few packets
nickelpro Nov 13, 2014
641c752
Finished protocol work
nickelpro Nov 14, 2014
5d3f170
Readme Update
nickelpro Nov 14, 2014
ec5873e
Everything works if you dont count compression
nickelpro Nov 14, 2014
681ebf8
Much thanks to dx, compression working
nickelpro Nov 14, 2014
397f6a5
Readme Update, soonish was very soon indeed
nickelpro Nov 15, 2014
4d6238e
Try to fix slots, totally untested
nickelpro Dec 14, 2014
91a59af
Fix incorrect decoder for updating NBT data
nickelpro Dec 14, 2014
90cbfdd
Minor fixes
nickelpro Dec 21, 2014
80d3737
Fixed off by one error in packet size, and datatype of keep_alive
gamingrobot Jan 1, 2015
d1d8c48
Fixed rep and selectedProfile not being defined for offline or demo a…
gamingrobot Jan 1, 2015
91f27cb
Merge pull request #27 from gamingrobot/offlineaccount-fix
Jan 2, 2015
f6ddd46
Merge pull request #28 from gamingrobot/keepalive-fix
Jan 2, 2015
4dc2b29
Minor bug fix related to particles
nickelpro Jan 2, 2015
5775ab4
Merge branch 'master' of github.com:nickelpro/spock
nickelpro Jan 2, 2015
1166fc5
I knew that off-by-one was in the wrong place
nickelpro Jan 2, 2015
1a96313
Added /build to .gitignore because of setup.py install
gamingrobot Jan 2, 2015
28103d8
Fixed self.connected not getting set properly
gamingrobot Jan 2, 2015
3171c37
Update smpmap for MC1.8, untested
nickelpro Jan 2, 2015
2c72cad
Added Chunk Data packet to ignore for EchoPacket plugin
gamingrobot Jan 2, 2015
1211df2
Taking out the trash
nickelpro Jan 2, 2015
b5ade5b
Allows packets to be identified by string
nickelpro Jan 2, 2015
eaebbd7
Fixed move plugin, Added respawn plugin
gamingrobot Jan 2, 2015
7bcc856
Changed handle00 to handle_keep_alive
gamingrobot Jan 2, 2015
13eac43
Fixed packet type in mcpacket_extentions
gamingrobot Jan 2, 2015
c77d9fc
Updated class name for Tab-Complete extension
gamingrobot Jan 2, 2015
2668d4f
Timers are back
nickelpro Jan 2, 2015
9807326
Add ticker plugin to core in order to simulate client and physics ticks
nickelpro Jan 2, 2015
ef2f248
Fixed ticker class
gamingrobot Jan 2, 2015
7a0e388
Fixed more conflicts
gamingrobot Jan 2, 2015
1e09fe9
Add client status constants to mcdata
nickelpro Jan 2, 2015
0ef48be
Fixed Entity Equipment packet
nickelpro Jan 2, 2015
0bc4293
Removed spam from sending position
gamingrobot Jan 2, 2015
f29a0bd
Finished respawn plugin
gamingrobot Jan 2, 2015
ccfe384
Print broken decode, then skip
nickelpro Jan 3, 2015
4397fea
More comprehensive packet check
nickelpro Jan 3, 2015
eb16fdd
Start tickers on PLAY_STATE
nickelpro Jan 3, 2015
1077835
Rough but working world module
nickelpro Jan 3, 2015
a54314b
Added disconnect event
gamingrobot Jan 4, 2015
a53fc7b
tick -> event_tick
nickelpro Jan 4, 2015
37cdb53
Fixed event_tick
gamingrobot Jan 4, 2015
0111fcc
Changed PollSocket to SelectSocket for both Windows and *nix
gamingrobot Jan 4, 2015
e286986
More magic vals for the magic val god
nickelpro Jan 4, 2015
cc1df9e
Trivial change to socket poll
nickelpro Jan 4, 2015
3d881a7
Syntax errors making me look like a bad programmer
nickelpro Jan 4, 2015
f26bf9e
Comments, comments everywhere
nickelpro Jan 4, 2015
6c8e63b
Timers now default to infinite run
nickelpro Jan 4, 2015
b7b0428
Removed some remains of threadpool
gamingrobot Jan 4, 2015
829fdcb
Moved comments to top of module to work with documentation generators
gamingrobot Jan 4, 2015
3fa0010
ClientInfo now works as intended, tiny net update
nickelpro Jan 4, 2015
501ea29
Net now handles PLAY<Disconnect
gamingrobot Jan 4, 2015
8b9123f
The always important ReadMe and license update
nickelpro Jan 4, 2015
b9dfcdd
comment signal calls, we're not in the main thread
Doik Jan 25, 2015
b65bf03
adjust tick rates. seems to mitigate the bad packages problem
Doik Jan 25, 2015
2f4ee32
crude sort-of-fix for packing location
Doik Jan 25, 2015
ee2ca2e
make spock work while offline
Doik Jan 30, 2015
2d626d3
fix taken from `b0aba5b`
Doik Feb 2, 2015
80c7040
prevent plugins from being initialized several times
Doik Feb 6, 2015
f69bb5a
make movementplugin use clientinfo.position
Doik Feb 6, 2015
418ff32
a bit faster tickrate
Doik Feb 6, 2015
5afc7b7
Merge remote-tracking branch 'micropsi-industries/master' into micropsi
Doik Feb 6, 2015
23f08a3
emit the use-bed package even if decoding failed
Doik Mar 2, 2015
18964de
Revert "emit the use-bed package even if decoding failed"
Doik Apr 4, 2015
3438b6f
prepare net for reconnect
Doik Apr 13, 2015
08b8b45
modified reconnect plugin
Doik Apr 13, 2015
da5a2f1
during reconnect, queue packets for later sending
Doik Apr 13, 2015
2a0b568
revised reconnect with exponential wait
Doik Apr 20, 2015
c337a9b
reconnect: use start() again, otherwise the client won't authenticate…
Doik May 12, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.pyc
*.log
login.py
run.py
run.py
/build
43 changes: 29 additions & 14 deletions ReadMe.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
Inspired by remyroy's COPS, a Minecraft client in Python. Protocol implementation based on barneymc
Currently Supports Minecraft 1.7.4

Spock currently supports Minecraft 1.8.1

spock
=====

Bot framework, currently under heavy development

Protocol stuff lives in spock/mcp
Map stuff lives in spock/mcmap
Important client stuff lives in spock/plugins/core
Less important stuff lives in spock/plugins/helpers

Client could loosely be called "event-driven", by default plugins register handler functions to handle events that may or may not be emitted by other plugins. Everything is a plugin in spock, including the event loop/framework itself, so you can feel free to rip out the entire back end and replace it with your framework or paradigm of choice. As long as you provide the same simple APIs, other plugins won't know the difference.

Currently writing Spock plugins requires a fairly intricate understanding of the MC protocol, since there aren't many plugins that provide higher abstractions than MC packets. That said the API is starting to shape up quite nicely, we've got threading and the start of a World API. Once Python 3.4 comes out we'll probably try to stablize the event loop API around asyncio and provide some sort of ghetto fallback for older Python 3.x
Protocol stuff lives in spock/mcp
Map stuff lives in spock/mcmap
Important client stuff lives in spock/plugins/core
Less important stuff lives in spock/plugins/helpers

Client could loosely be called "event-driven", by default plugins register
handler functions to handle events that may or may not be emitted by other
plugins. Everything is a plugin in spock, including the event loop/framework
itself, so you can feel free to rip out the entire back end and replace it with
your framework or paradigm of choice. As long as you provide the same simple
APIs, other plugins won't know the difference.

Currently writing Spock plugins requires a fairly intricate understanding of the
MC protocol, since there aren't many plugins that provide higher abstractions
than MC packets. That said the API is starting to shape up quite nicely, we've
got timers and the start of a World API.

Speaking of compatibility, Spock runs on Python 3.x on *Nix operating systems,
and requires PyCrypto. Theoretically it runs on Windows but no one has ever
tested it and I'm fairly sure there are a couple (easy to fix) errors that will
pop up. Python 2.x would be nice, but it becomes an ever more distant goal as
Spock continues to grow dependencies on new Python features. Not impossible,
just not a priority

Speaking of compatibility, Spock runs on Python 3.x on *Nix operating systems, and requires PyCrypto. Theoretically it runs on Windows but no one has ever tested it and I'm fairly sure there are a couple (easy to fix) errors that will
pop up. Python 2.x would be nice, but it becomes an ever more distant goal as Spock continues to grow dependencies on new Python features. Not impossible, just not a priority

I'll write a real ReadMe and API docs when everything is done and stable-ish.
For now you can check out the plugins folder to get a vague idea of what plugins should look like, find me on #mcdevs or email me at nickelpro@gmail.com if you have questions
For now you can check out the plugins folder to get a vague idea of what plugins
should look like, find me on #mcdevs or email me at nickelpro@gmail.com if you
have questions


###Legal

License is MIT and can be found in license.md

The NBT parser and the original protocol implementation came from other projects,
The NBT parser and the original protocol implementation came from other projects,
relevant legal information and attribution can be found in legal.md
27 changes: 7 additions & 20 deletions examples/demo.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
"""
Basic demo example
"""

from spock.client import Client
from spock.plugins import DefaultPlugins
from demoplugin import DemoPlugin
#Open login.py and put in your username and password
from login import username, password
from spock.plugins.helpers.clientinfo import ClientInfoPlugin
from spock.plugins.helpers.move import MovementPlugin

settings = {
'username': "Bot",
'authenticated': False, #Authenticate with authserver.mojang.com
'bufsize': 4096, #Size of socket buffer
'sock_quit': True, #Stop bot on socket error or hangup
'sess_quit': True, #Stop bot on failed session login
'thread_workers': 5, #Number of workers in the thread pool
'packet_trace': True,
'plugins': DefaultPlugins, #Plugins
'plugin_settings': {}, #Extra settings for plugins
}

plugins = DefaultPlugins
plugins.append(ClientInfoPlugin)
plugins.append(MovementPlugin)
# plugins.append(DemoPlugin)

client = Client(plugins = plugins, settings = settings)
client.start(host="192.168.2.19", port=25565)
plugins.append(DemoPlugin)
client = Client(plugins = plugins, username = username, password = password)
client.start()
36 changes: 18 additions & 18 deletions examples/demoplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@

#TODO: Make this cooler
class DemoPlugin:
def __init__(self, ploader, settings):
#Login Success
ploader.reg_event_handler(
(mcdata.LOGIN_STATE, mcdata.SERVER_TO_CLIENT, 0x02),
self.print_packets
)
#Chat Message
ploader.reg_event_handler(
(mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x02),
self.print_packets
)
#Player List Item
ploader.reg_event_handler(
(mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x38),
self.print_packets
)
def __init__(self, ploader, settings):
#Login Success
ploader.reg_event_handler(
(mcdata.LOGIN_STATE, mcdata.SERVER_TO_CLIENT, 0x02),
self.print_packets
)
#Chat Message
ploader.reg_event_handler(
(mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x02),
self.print_packets
)
#Player List Item
ploader.reg_event_handler(
(mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x38),
self.print_packets
)

def print_packets(self, name, packet):
print(packet)
def print_packets(self, name, packet):
print(packet)
2 changes: 1 addition & 1 deletion examples/login.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
username = 'Put Your Username Here'
password = 'Put Your Password Here'
password = 'Put Your Password Here'
17 changes: 8 additions & 9 deletions examples/settings.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from spock.plugins.defaults import DefaultPlugins

default_settings = {
'username': 'Bot', #minecraft.net username or name for unauthenticated servers
'password': '', #Password for account, ignored if not authenticated
'authenticated': True, #Authenticate with authserver.mojang.com
'bufsize': 4096, #Size of socket buffer
'sock_quit': True, #Stop bot on socket error or hangup
'sess_quit': True, #Stop bot on failed session login
'thread_workers': 5, #Number of workers in the thread pool
'plugins': DefaultPlugins, #Plugins
'plugin_settings': {}, #Extra settings for plugins
'username': 'Bot', #minecraft.net username or name for unauthenticated servers
'password': '', #Password for account, ignored if not authenticated
'authenticated': True, #Authenticate with authserver.mojang.com
'bufsize': 4096, #Size of socket buffer
'sock_quit': True, #Stop bot on socket error or hangup
'sess_quit': True, #Stop bot on failed session login
'plugins': DefaultPlugins, #Plugins
'plugin_settings': {}, #Extra settings for plugins
}
4 changes: 2 additions & 2 deletions license.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (C) 2013 Nick Gamberini
Copyright (C) 2015 Nick Gamberini

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -16,4 +16,4 @@ Copyright (C) 2013 Nick Gamberini
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.
28 changes: 14 additions & 14 deletions plugins/AntiAFK.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@

#Very bad and naive Anti-AFK plugin
class AntiAFKPlugin:
def __init__(self, client, settings):
self.client = client
client.register_dispatch(self.avoid_afk, 0x03)
client.register_dispatch(self.revive, 0x08)
def __init__(self, client, settings):
self.client = client
client.register_dispatch(self.avoid_afk, 0x03)
client.register_dispatch(self.revive, 0x08)

def avoid_afk(self, packet):
msg = packet.data['text'].lower()
if ('afk plugin' in msg):
self.client.push(Packet('PLAY>Chat Message', data={
"text": "Hello, I am Spock_Bot, this message is to avoid AFKGC"
})
)
def avoid_afk(self, packet):
msg = packet.data['text'].lower()
if ('afk plugin' in msg):
self.client.push(Packet(ident=0x03, data={
"text": "Hello, I am Spock_Bot, this message is to avoid AFKGC"
})
)

def revive(self, packet):
if self.client.health['health']<=0:
self.client.push(Packet(ident='PLAY>Client Status', data={'action': 0}))
def revive(self, packet):
if self.client.health['health']<=0:
self.client.push(Packet(ident=0xCD, data={'payload': 1}))
46 changes: 22 additions & 24 deletions plugins/DebugPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,31 @@
from spock.mcmap import mapdata
from spock.mcp import mcdata
from spock.utils import pl_announce
import time

class DebugPlugin:
def __init__(self, ploader, settings):
for packet in mcdata.hashed_structs:
ploader.reg_event_handler(packet, self.debug)
#ploader.reg_event_handler('tick', self.tick)
#ploader.reg_event_handler('w_map_chunk', self.map)
#ploader.reg_event_handler('w_block_update', self.block_update)
def __init__(self, ploader, settings):
#for packet in mcdata.hashed_structs:
# ploader.reg_event_handler(packet, self.debug)
#ploader.reg_event_handler('w_block_update', self.block_test)
#ploader.reg_event_handler('client_tick', self.timer_test)
ploader.reg_event_handler('cl_health_update', self.clinfo_test)
self.old_time = 0

def debug(self, name, packet):
if packet.ident() == (mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x26):
packet.data['data'] = b''
#print(packet)
#print(packet)
def debug(self, name, packet):
if packet.ident() == (mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x26):
packet.data['data'] = b''
#print(packet)
#print(packet)

def block_update(self, name, data):
print('Block Updated!')
print(
'Block is:', mapdata.blocks[data.id]['display_name']+',',
'Biome:', mapdata.biomes[data.biome]['display_name']
)
print('Block Light:', str(data.block_light)+',', 'Sky Light:', data.sky_light)
def clinfo_test(self, event, data):
print('Health Update', data)

def block_test(self, event, block):
print('Block update at:', block['location'])
print('New block data:', block['block_data'])

def map(self, name, data):
print(data)

def tick(self, name, data):
print('tick!')
print('Current threads:', threading.active_count())
def timer_test(self, _, __):
new_time = int(round(time.time() * 1000))
print(new_time - self.old_time)
self.old_time = new_time
14 changes: 9 additions & 5 deletions plugins/EchoPacket.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from spock.mcp.mcdata import structs
from spock.mcp.mcdata import hashed_structs
from spock.mcp import mcdata

class EchoPacketPlugin:
def __init__(self, ploader, settings):
ploader.reg_event_handler(list(structs.keys()), self.echopacket)
def __init__(self, ploader, settings):
for i in list(hashed_structs.keys()):
ploader.reg_event_handler(i, self.echopacket)

def echopacket(self, name, packet):
print(packet)
def echopacket(self, name, packet):
#Dont print Chunk Data and Map Chunk Bulk
if packet.ident != (mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x26) and packet.ident != (mcdata.PLAY_STATE, mcdata.SERVER_TO_CLIENT, 0x21) and packet.ident != (mcdata.PLAY_STATE, mcdata.CLIENT_TO_SERVER, 0x04):
print(packet)
71 changes: 35 additions & 36 deletions plugins/ReConnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,44 @@
In the meantime, go look at plugins in spock.net.plugins for more up-to-date plugin examples
"""

import threading
from spock.mcp.mcpacket import Packet
from spock.net.cflags import cflags
from spock.net.timer import EventTimer

#Will relentlessly try to reconnect to a server
class ReConnectPlugin:
def __init__(self, client, settings):
self.client = client
self.lock = False
self.kill = False
self.delay = 0

client.register_handler(self.start_timer, cflags['SOCKET_ERR'], cflags['SOCKET_HUP'])
client.register_handler(self.stop, cflags['KILL_EVENT'])
client.register_dispatch(self.start_timer, 0xFF)
client.register_dispatch(self.grab_host, 0x02)
client.register_dispatch(self.reset_reconnect_time, 0x01)

def start_timer(self, *args):
if not self.lock:
self.client.register_timer(EventTimer(self.delay, self.reconnect))
self.lock = True

def stop(self, *args):
self.kill = True

def reconnect(self, *args):
if not self.kill:
if self.delay < 300:
self.delay += 30
self.client.start_session(self.client.mc_username, self.client.mc_password)
self.client.login(self.host, self.port)
self.lock = False

def reset_reconnect_time(self, *args):
self.delay = 0

#Grabs host and port on handshake
def grab_host(self, packet):
self.host = packet.data['host']
self.port = packet.data['port']
def __init__(self, client, settings):
self.client = client
self.lock = False
self.kill = False
self.delay = 0

client.register_handler(self.start_timer, cflags['SOCKET_ERR'], cflags['SOCKET_HUP'])
client.register_handler(self.stop, cflags['KILL_EVENT'])
client.register_dispatch(self.start_timer, 0xFF)
client.register_dispatch(self.grab_host, 0x02)
client.register_dispatch(self.reset_reconnect_time, 0x01)

def start_timer(self, *args):
if not self.lock:
self.client.register_timer(EventTimer(self.delay, self.reconnect))
self.lock = True

def stop(self, *args):
self.kill = True

def reconnect(self, *args):
if not self.kill:
if self.delay < 300:
self.delay += 30
self.client.start_session(self.client.mc_username, self.client.mc_password)
self.client.login(self.host, self.port)
self.lock = False

def reset_reconnect_time(self, *args):
self.delay = 0

#Grabs host and port on handshake
def grab_host(self, packet):
self.host = packet.data['host']
self.port = packet.data['port']
12 changes: 6 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
name='spock',
version='1.2',
packages=[
'spock',
'spock.mcp',
'spock.mcmap',
'spock.plugins',
'spock.plugins.core',
'spock.plugins.helpers',
'spock',
'spock.mcp',
'spock.mcmap',
'spock.plugins',
'spock.plugins.core',
'spock.plugins.helpers',
],
)
Loading