Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
max-mapper committed Mar 13, 2013
0 parents commit f305036
Show file tree
Hide file tree
Showing 18 changed files with 51,043 additions and 0 deletions.
23 changes: 23 additions & 0 deletions chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = function(name, emitter) {
// Handle entering a command
window.addEventListener('keyup', function(e) {
if (e.keyCode !== 13) return;
var el = document.getElementById('cmd');
if (document.activeElement === el) {
emitter.emit('message', {user: name, text: el.value})
el.value = '';
el.blur();
} else {
el.focus();
}
});

emitter.on('message', showMessage)

function showMessage(message) {
var li = document.createElement('li')
li.innerHTML = message.user + ': ' + message.text
messages.appendChild(li)
messages.scrollTop = messages.scrollHeight
}
}
185 changes: 185 additions & 0 deletions client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
var url = require('url')
var websocket = require('websocket-stream')
var engine = require('voxel-engine')
var duplexEmitter = require('duplex-emitter')
var toolbar = require('toolbar')
var randomName = require('./randomname')
var crunch = require('voxel-crunch')
var emitChat = require('./chat')
var blockSelector = toolbar({el: '#tools'})
var highlight = require('voxel-highlight')
var skin = require('minecraft-skin')
var player = require('voxel-player')

var playerID
var lastProcessedSeq = 0
var localInputs = [], connected = false, erase = true
var currentMaterial = 1
var lerpPercent = 0.1

function Client(server, options) {
this.server = server || 'ws://' + url.parse(window.location.href).host
this.others = {}
this.connect(server)
}

Client.prototype.connect = function(server) {
var self = this
var socket = websocket(server)
socket.on('end', function() { self.connected = false })
this.socket = socket
this.bindEvents(socket)
}

Client.prototype.bindEvents = function(socket) {
var self = this
this.emitter = duplexEmitter(socket)
this.connected = true

emitter.on('id', function(id) {
self.playerID = id
})

emitter.on('settings', function(settings) {
settings.generateChunks = false
window.game = game = createGame(settings)
emitter.emit('created')
emitter.on('chunk', function(encoded, chunk) {
var voxels = crunch.decode(encoded, chunk.length)
chunk.voxels = voxels
game.showChunk(chunk)
})
})

// fires when server sends us voxel edits
emitter.on('set', function(pos, val) {
game.setBlock(pos, val)
})
}

function createGame(options) {
options.controlsDisabled = false
window.game = engine(options)

function sendState() {
if (!connected) return
var state = {
position: viking.yaw.position,
rotation: {
y: viking.yaw.rotation.y,
x: viking.pitch.rotation.x
}
}
emitter.emit('state', state)
}

var name = localStorage.getItem('name')
if (!name) {
name = randomName()
localStorage.setItem('name', name)
}

game.controls.on('data', function(state) {
var interacting = false
Object.keys(state).map(function(control) {
if (state[control] > 0) interacting = true
})
if (interacting) sendState()
})

emitChat(name, emitter)

var container = document.querySelector('#container')
game.appendTo(container)
// rescue(game)
var createPlayer = player(game)
var viking = createPlayer('viking.png')
viking.moveTo(options.startingPosition)
viking.possess()

highlight(game)

blockSelector.on('select', function(material) {
currentMaterial = +material
})

game.on('fire', function (target, state) {
var vec = game.cameraVector()
var pos = game.cameraPosition()
var point = game.raycast(pos, vec, 100)
if (!point) return
var erase = !state.firealt && !state.alt
var size = game.cubeSize
if (erase) {
emitter.emit('set', {x: point.x, y: point.y, z: point.z}, 0)
} else {
var newBlock = game.checkBlock(point)
if (!newBlock) return
var direction = game.camera.matrixWorld.multiplyVector3(new game.THREE.Vector3(0,0,-1))
var diff = direction.subSelf(game.controls.target().yaw.position.clone()).normalize()
diff.multiplySelf({ x: 1, y: 1, z: 1 })
var p = point.clone().addSelf(diff)
emitter.emit('set', p, currentMaterial)
}
})

// setTimeout is because three.js seems to throw errors if you add stuff too soon
setTimeout(function() {
emitter.on('update', function(updates) {
Object.keys(updates.positions).map(function(player) {
var update = updates.positions[player]
if (player === playerID) return onServerUpdate(update) // local player
updatePlayerPosition(player, update) // other players
})
})
}, 1000)

emitter.on('leave', function(id) {
if (!players[id]) return
game.scene.remove(players[id].mesh)
delete players[id]
})

return game
}

function onServerUpdate(update) {
var pos = game.controls.target().yaw.position
var distance = pos.distanceTo(update.position)
// todo use server sent location
}

function lerpMe(position) {
var to = new game.THREE.Vector3()
to.copy(position)
var from = game.controls.target().yaw.position
from.copy(from.lerpSelf(to, lerpPercent))
}

function updatePlayerPosition(id, update) {
var pos = update.position
var player = players[id]
if (!player) {
var playerSkin = skin(game.THREE, 'viking.png')
var playerMesh = playerSkin.mesh
players[id] = playerSkin
playerMesh.children[0].position.y = 10
game.scene.add(playerMesh)
}
var playerSkin = window.playerSkin = players[id]
var playerMesh = playerSkin.mesh.children[0]
playerMesh.position.copy(pos, lerpPercent)

var to = new game.THREE.Vector3()
to.copy(pos)
var from = playerMesh.position
from.copy(from.lerpSelf(to, lerpPercent))

playerMesh.position.y += 17
playerMesh.rotation.y = update.rotation.y + (Math.PI / 2)
playerSkin.head.rotation.z = scale(update.rotation.x, -1.5, 1.5, -0.75, 0.75)
}

function scale( x, fromLow, fromHigh, toLow, toHigh ) {
return ( x - fromLow ) * ( toHigh - toLow ) / ( fromHigh - fromLow ) + toLow
}
6 changes: 6 additions & 0 deletions demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
window.addEventListener('keydown', function (ev) {
if (ev.keyCode === 'X'.charCodeAt(0)) erase = !erase
})
function ctrlToggle (ev) { erase = !ev.ctrlKey }
window.addEventListener('keyup', ctrlToggle)
window.addEventListener('keydown', ctrlToggle)
4 changes: 4 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
server: require('./server'),
client: require('./client')
}
16 changes: 16 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "voxel-client",
"description": "multiplayer client for voxel-server"
"version": "0.0.1",
"dependencies": {
"voxel-engine": "0.5.7",
"voxel-crunch": "0.1.0",
"websocket-stream": "0.0.5",
"ws": "0.4.25",
"hat": "0.0.3",
"duplex-emitter": "0.1.6"
},
"engines": {
"node": "0.8.x"
}
}
15 changes: 15 additions & 0 deletions randomname.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var names = ['alpha', 'space', 'beta', 'omega', 'zone', 'base', 'bass', 'centaur', 'official', 'free', 'fresh', 'freedom', 'power', 'synth', 'lazer', 'gamma', 'red', 'green', 'ultra', 'net', 'cafe', 'secret', 'open', 'track', 'wisdom', 'genghis', 'tron', 'grid', 'plus', 'maximum', 'pre', 'post', 'mid', 'pyramid', 'core', 'fast', 'dragon', 'wizard', 'yak', 'crystal', 'electric', 'rizzle', 'tiny', 'pantry', 'dry', 'bleeding', 'fruit', 'mower', 'whiskey', 'marble', 'cake', 'meat', 'donkey','wewo', 'banana', 'rooster', 'bear', 'bacon', 'moon', 'glitter', 'grandma', 'walrus', 'party', 'junk', 'crazy', 'turbo', 'hyper', 'mega', 'boss', 'dunk', 'pow', 'icy', 'bobo', 'pile', 'tater', 'wiz', 'gnarl', 'mix', 'pop', 'mustard', 'bizzler', 'fog', 'punch', 'planar']

module.exports = function(len) {
len = len || 2
var name = ''
while (len > 0) {
name += randomName()
len--
}
return name
}

function randomName() {
return names[~~(Math.random() * names.length)]
}
Loading

0 comments on commit f305036

Please sign in to comment.