/************************************************************************* ## Cow Clicker Mini-Game ### How to Play At the in-game prompt type `jsp cowclicker` to start or stop playing. Right-Click on Cows to score points. No points for killing cows (hint: use the same keyboard keys you'd use for opening doors). Every time you click a cow your score increases by 1 point. Your score is displayed in a side-bar along the right edge of of the screen. ![cow clicker](img/cowclicker.png) ### Rules * You can join and leave the Cow Clicker game at any time by typing `/jsp cowclicker` at the in-game prompt. * Once you leave the game, your score is reset to zero. * You can disconnect from the server and your score will be saved for the next time you join. ### Gameplay Mechanics This is meant as a trivially simple use of the [Bukkit Scoreboard API][bukscore]. There are many things you'll want to consider when constructing your own mini-game... * Is the game itself a long-lived game - that is - should players and scores be persisted (stored) between server restarts? * What should happen when a player quits the server - should this also be understood as quitting the mini-game? * What should happen when a player who was previously playing the mini-game, joins the server - should they automatically resume the mini-game? [bukscore]: http://jd.bukkit.org/beta/apidocs/org/bukkit/scoreboard/package-summary.html ***/ var store = {}; var scoreboardConfig = { cowclicker: {SIDEBAR: 'Cows Clicked'} }; /* The scoreboard is a simple wrapper around the Bukkit Scoreboard API. It's only concerned with display of scores, not maintaining them - that's the game's job. */ var scoreboard = (function(options){ var temp = {}; var ccScoreboard; var DisplaySlot = org.bukkit.scoreboard.DisplaySlot; return { start: function(){ var objective, slot; ccScoreboard = server.scoreboardManager.getNewScoreboard(); for (objective in options){ var ccObj = ccScoreboard.registerNewObjective(objective,'dummy'); for (slot in options[objective]){ ccObj.displaySlot = DisplaySlot[slot]; ccObj.displayName = options[objective][slot]; } } }, stop: function(){ var objective, slot; for (objective in options){ ccScoreboard.getObjective(objective).unregister(); for (slot in options[objective]){ ccScoreboard.clearSlot(DisplaySlot[slot]); } } }, update: function(objective,player,score){ if (player.scoreboard && player.scoreboard != ccScoreboard) { temp[player.name] = player.scoreboard; player.scoreboard = ccScoreboard; } ccScoreboard.getObjective(objective).getScore(player).score = score; }, restore: function(player){ // offlineplayers don't have a scoreboard if (player.scoreboard) player.scoreboard = temp[player.name]; } }; }(scoreboardConfig)); var _onPlayerInteract = function(listener, event){ var player = event.player; var Bukkit = org.bukkit.Bukkit; if (!store[player.name]) return; var clickedEntity = event.rightClicked; var loc = clickedEntity.location; var sound = function(snd,vol,pitch){ loc.world.playSound(loc,snd,vol,pitch); }; if (clickedEntity instanceof org.bukkit.entity.Cow) { store[player.name].score++; scoreboard.update('cowclicker', player, store[player.name].score); Bukkit.dispatchCommand(player, 'me clicked a cow!'); sound(org.bukkit.Sound.CLICK,1,1); setTimeout(function(){ sound(org.bukkit.Sound.COW_HURT,10,0.85) },200); } }; var _onPlayerQuit = function(listener, event){ _removePlayer(event.player) }; var _onPlayerJoin = function(listener, event){ var gamePlayer = store[event.player.name]; if (gamePlayer) _addPlayer(event.player, gamePlayer.score); }; var _startGame = function(){ if (config.verbose) console.log('Staring game: Cow Clicker'); events.on('player.PlayerQuitEvent', _onPlayerQuit); events.on('player.PlayerJoinEvent', _onPlayerJoin); events.on('player.PlayerInteractEntityEvent', _onPlayerInteract); scoreboard.start(); store = persist('cowclicker',store); for (var p in store){ var player = server.getPlayer(p); if (player){ /* only add online players */ var score = store[p].score; _addPlayer(player, score); } } }; var _addPlayer = function(player,score){ if (config.verbose) console.log('Adding player %s to Cow Clicker game',player); if (typeof score == 'undefined') score = 0; store[player.name] = {score: score}; scoreboard.update('cowclicker', player,store[player.name].score); player.sendMessage('Go forth and click some cows!'); }; var _removePlayer = function(player,notify){ if (player instanceof org.bukkit.OfflinePlayer && player.player) player = player.player; if (!store[player.name]) return; if (config.verbose) console.log('Removing player %s from Cow Clicker', player); var playerScore = store[player.name].score; scoreboard.restore(player); delete store[player.name]; if (notify && player){ player.sendMessage('You clicked ' + playerScore + ' cows! ' + 'You must be tired after all that clicking.'); } }; var _removeAllPlayers = function(notify){ if (typeof notify == 'undefined') notify = false; for (var p in store){ var player = server.getOfflinePlayer(p); if (player) _removePlayer(player,notify); delete store[p]; } } var _stopGame = function(removePlayers){ if (typeof removePlayers == 'undefined') removePlayers = true; if (config.verbose) console.log('Stopping game: Cow Clicker'); scoreboard.stop(); if (!removePlayers) return; _removeAllPlayers(false); persist('cowclicker',store.pers,'w'); }; /* start the game automatically when this module is loaded. */ _startGame(); /* players can join and leave the game by typing `jsp cowclicker` */ command('cowclicker', function(params, sender){ if (!store[sender.name]) _addPlayer(sender); else _removePlayer(sender); }); /* stop the game when ScriptCraft is unloaded. */ addUnloadHandler(function(){ _stopGame(false); });