mirror of
https://github.com/danbulant/flying-squid
synced 2026-06-15 04:21:04 +00:00
commit
5bff660bbe
20 changed files with 752 additions and 217 deletions
2
TODO.md
2
TODO.md
|
|
@ -20,11 +20,11 @@ This is a list that will keep the developers and the community organized!
|
|||
- [x] Other dimensions
|
||||
- [x] Block dropping
|
||||
- [x] Entity basics
|
||||
- [x] Plugin System
|
||||
|
||||
### To-do
|
||||
#### Priority
|
||||
- [ ] Inventories (saving the blocks players get)
|
||||
- [ ] Plugin System
|
||||
- [ ] Crafting and Smelting
|
||||
- [ ] Add in cluster functionality
|
||||
|
||||
|
|
|
|||
476
doc/api.md
476
doc/api.md
|
|
@ -19,6 +19,7 @@
|
|||
- [serv.time](#servtime)
|
||||
- [serv.tickCount](#servtickcount)
|
||||
- [serv.doDaylightCycle](#servdodaylightcycle)
|
||||
- [serv.plugins](#servplugins)
|
||||
- [Events](#events)
|
||||
- ["error" (error)](#error-error)
|
||||
- ["clientError" (client,error)](#clienterror-clienterror)
|
||||
|
|
@ -48,21 +49,72 @@
|
|||
- [server._writeAll(packetName, packetFields)](#server_writeallpacketname-packetfields)
|
||||
- [server._writeArray(packetName, packetFields, playerArray)](#server_writearraypacketname-packetfields-playerarray)
|
||||
- [server._writeNearby(packetName, packetFields, loc)](#server_writenearbypacketname-packetfields-loc)
|
||||
- [Player](#player)
|
||||
- [Entity](#entity-1)
|
||||
- [Properties](#properties-1)
|
||||
- [player.entity](#playerentity)
|
||||
- [entity.id](#entityid)
|
||||
- [entity.position](#entityposition)
|
||||
- [entity.world](#entityworld)
|
||||
- [entity.type](#entitytype)
|
||||
- [entity.entityType](#entityentitytype)
|
||||
- [entity.nearbyEntities](#entitynearbyentities)
|
||||
- [entity.viewDistance](#entityviewdistance)
|
||||
- [entity.health](#entityhealth)
|
||||
- [entity.pitch](#entitypitch)
|
||||
- [entity.headPitch](#entityheadpitch)
|
||||
- [entity.yaw](#entityyaw)
|
||||
- [entity.gravity](#entitygravity)
|
||||
- [entity.terminalvelocity](#entityterminalvelocity)
|
||||
- [entity.friction](#entityfriction)
|
||||
- [entity.size](#entitysize)
|
||||
- [entity.deathTime](#entitydeathtime)
|
||||
- [entity.pickupTime](#entitypickuptime)
|
||||
- [entity.bornTime](#entityborntime)
|
||||
- [entity.itemId](#entityitemid)
|
||||
- [entity.itemDamage](#entityitemdamage)
|
||||
- [entity.metadata](#entitymetadata)
|
||||
- [entity.nearbyEntities](#entitynearbyentities-1)
|
||||
- [Events](#events-1)
|
||||
- [Behaviors](#behaviors)
|
||||
- [FORMAT](#format)
|
||||
- ["move"](#move)
|
||||
- [Methods](#methods-1)
|
||||
- [entity.getData(pluginName)](#entitygetdatapluginname)
|
||||
- [entity.getOthers()](#entitygetothers)
|
||||
- [entity.getOtherPlayers()](#entitygetotherplayers)
|
||||
- [entity.getNearby()](#entitygetnearby)
|
||||
- [entity.getNearbyPlayers()](#entitygetnearbyplayers)
|
||||
- [entity.nearbyPlayers()](#entitynearbyplayers)
|
||||
- [Low level Methods](#low-level-methods)
|
||||
- [entity._writeOthers(packetName, packetFields)](#entity_writeotherspacketname-packetfields)
|
||||
- [entity._writeOthersNearby(packetName, packetFields)](#entity_writeothersnearbypacketname-packetfields)
|
||||
- [Player](#player)
|
||||
- [Properties](#properties-2)
|
||||
- [player.username](#playerusername)
|
||||
- [player.view](#playerview)
|
||||
- [player.world](#playerworld)
|
||||
- [player.nearbyPlayers](#playernearbyplayers)
|
||||
- [Events](#events-1)
|
||||
- [Events](#events-2)
|
||||
- ["connected"](#connected)
|
||||
- ["spawned"](#spawned)
|
||||
- ["disconnected"](#disconnected)
|
||||
- ["chat" (message)](#chat-message)
|
||||
- ["kicked" (kicker,reason)](#kicked-kickerreason)
|
||||
- ["positionChanged"](#positionchanged)
|
||||
- [Methods](#methods-1)
|
||||
- [Behaviors](#behaviors-1)
|
||||
- ["move"](#move-1)
|
||||
- ["look"](#look)
|
||||
- ["chat"](#chat)
|
||||
- ["command"](#command)
|
||||
- ["punch"](#punch)
|
||||
- ["sendBlock"](#sendblock)
|
||||
- ["sendChunk"](#sendchunk)
|
||||
- ["dig"](#dig)
|
||||
- ["dug"](#dug)
|
||||
- ["cancelDig"](#canceldig)
|
||||
- ["forceCancelDig"](#forcecanceldig)
|
||||
- ["breakAnimation"](#breakanimation)
|
||||
- ["placeBlock"](#placeblock)
|
||||
- ["attack"](#attack)
|
||||
- ["requestRespawn"](#requestrespawn)
|
||||
- [Methods](#methods-2)
|
||||
- [player.login()](#playerlogin)
|
||||
- [player.ban(reason)](#playerbanreason)
|
||||
- [player.kick(reason)](#playerkickreason)
|
||||
|
|
@ -83,8 +135,6 @@
|
|||
- [Low level properties](#low-level-properties)
|
||||
- [player._client](#player_client)
|
||||
- [Low level methods](#low-level-methods-1)
|
||||
- [player._writeOthers(packetName, packetFields)](#player_writeotherspacketname-packetfields)
|
||||
- [player._writeOthersNearby(packetName, packetFields)](#player_writeothersnearbypacketname-packetfields)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
|
|
@ -159,6 +209,10 @@ Best to use with modulo (e.g. Something every 10 seconds is `serv.tickCount % 20
|
|||
|
||||
Default `true`. If false, time will not automatically pass.
|
||||
|
||||
#### serv.plugins
|
||||
|
||||
List of all plugins. Use serv.plugins[pluginName] to get a plugin's object and data.
|
||||
|
||||
### Events
|
||||
|
||||
#### "error" (error)
|
||||
|
|
@ -293,13 +347,227 @@ Writes packet to every player in playerArray
|
|||
|
||||
Writes packet to all players within distance of loc. loc has the same paramater as loc in server.getNearby()
|
||||
|
||||
## Player
|
||||
## Entity
|
||||
|
||||
Players are a type of entity, so they will have most of the attributes and methods
|
||||
|
||||
### Properties
|
||||
|
||||
#### player.entity
|
||||
#### entity.id
|
||||
|
||||
The entity of the player, of type `Flying-squid.Entity`
|
||||
ID of entity on server
|
||||
|
||||
#### entity.position
|
||||
|
||||
Current position (currently in fixed position (x32 what you'd expect) so do entity.position.scaled(1/32) to get normal position)
|
||||
|
||||
#### entity.world
|
||||
|
||||
World object entity is in
|
||||
|
||||
#### entity.type
|
||||
|
||||
Either "player", "mob", or "object" (currently)
|
||||
|
||||
#### entity.entityType
|
||||
|
||||
Sub-category of entity. For mobs, this is which mob (Zombie/Skeleton, etc). For objects, this is which object (Arrow/Dropped item, etc)
|
||||
|
||||
#### entity.nearbyEntities
|
||||
|
||||
Nearby entities to this entity
|
||||
|
||||
#### entity.viewDistance
|
||||
|
||||
How far away entities are loaded/unloaded (used for players ATM)
|
||||
|
||||
#### entity.health
|
||||
|
||||
How many half-hearts an entity has of health (e.g. Player has 20). Not really used for objects, only players and mobs.
|
||||
|
||||
#### entity.pitch
|
||||
|
||||
Pitch of entity (rotation sideways)
|
||||
|
||||
#### entity.headPitch
|
||||
|
||||
Pitch of entity's head
|
||||
|
||||
#### entity.yaw
|
||||
|
||||
Yaw of entity (rotation looking up and down)
|
||||
|
||||
#### entity.gravity
|
||||
|
||||
Gravity of entity (non-players) to calculate physics.
|
||||
|
||||
#### entity.terminalvelocity
|
||||
|
||||
Only applies to gravity, really. You can still apply a velocity larger than terminal velocity.
|
||||
|
||||
#### entity.friction
|
||||
|
||||
Decreases velocity when touching blocks
|
||||
|
||||
#### entity.size
|
||||
|
||||
Used to calculate collisions for server-side entities
|
||||
|
||||
#### entity.deathTime
|
||||
|
||||
How much time before an entity despawns (in ms)
|
||||
|
||||
#### entity.pickupTime
|
||||
|
||||
How long before an entity can be picked up (in ms)
|
||||
|
||||
#### entity.bornTime
|
||||
|
||||
When an entity was born. Used with pickupTime and deathTime (time in epoch)
|
||||
|
||||
#### entity.itemId
|
||||
|
||||
If a block drop, what item id
|
||||
|
||||
#### entity.itemDamage
|
||||
|
||||
If a block drop, what item damage
|
||||
|
||||
#### entity.metadata
|
||||
|
||||
Metadata for the entity (not like block metadata/damage). Contains stuff like NBT.
|
||||
|
||||
#### entity.nearbyEntities
|
||||
|
||||
List of entities that the entity believes is nearby.
|
||||
|
||||
### Events
|
||||
|
||||
|
||||
|
||||
### Behaviors
|
||||
|
||||
Behaviors are very interesting. Let me explain to you how they work:
|
||||
|
||||
Behaviors are a special type of event. They are editable and allow defaults to be cancellable making the powerful
|
||||
for plugins to take control of and interact with each other. Three different events get called
|
||||
for a behavior:
|
||||
- EVENTNAME_cancel
|
||||
- EVENTNAME
|
||||
- EVENTNAME_done
|
||||
|
||||
EVENTNAME_cancel passses the paramaters `data` (object of all info about behavior. Changing the data could have effects on outcome) and `cancel`, a function. This event is run before the default action. If `cancel()` is called, it will cancel the default action. More on this later.
|
||||
|
||||
EVENTNAME passes `data` as well as `cancelled` so plugins can check if the default behavior has been cancelled. This is event is run
|
||||
before the default action.
|
||||
|
||||
EVENTNAME_done passes `data` and `cancelled`. This event is run before the default action.
|
||||
|
||||
Example: One plugin wants to cancel a player's movement while another wants to say "HI" when they move
|
||||
|
||||
Plugin A:
|
||||
```js
|
||||
player.on('move_cancel', ({position}, cancel) => {
|
||||
cancel(); // If player tries to move, shoots them back where they came from
|
||||
});
|
||||
```
|
||||
|
||||
Plugin B:
|
||||
```js
|
||||
player.on('move', ({position}, cancelled) => {
|
||||
if (!cancelled) player.chat('HI!');
|
||||
})
|
||||
```
|
||||
|
||||
When a player normally moves, the server saves their position and sends it to all clients. Therefore, if a "move" behavior was truly cancelled,
|
||||
the player would be able to move freely while the server and other players would see the player stationary. This doesn't happen because
|
||||
behaviors can have "default cancel functions". In the case of a player's "move", the default cancel function sends them back where they
|
||||
came from. To prevent this from happening, use the "preventDefaultCancel" paramater: cancel(false);
|
||||
|
||||
Plugin C
|
||||
```js
|
||||
player.on('move_cancel', ({position}, cancel) => {
|
||||
cancel(false); // Doesn't teleport player back
|
||||
});
|
||||
```
|
||||
|
||||
If we keep Plugin B and replace Plugin A with Plugin C, we'll see that the player can move freely but will not recieve the
|
||||
word "HI" and other players will be unable to see their movements.
|
||||
|
||||
Finally, there is hidden cancel. This is the second paramater in cancel, and allows plugins to hide the fact that they cancelled
|
||||
the default action from other plugins. It's best not to use this, but I know somebody will someday need this.
|
||||
|
||||
Plugin D
|
||||
```js
|
||||
player.on('move_cancel', ({position}, cancel) => {
|
||||
cancel(false, true); // Player doesn't teleport back and now "cancelled" will be false
|
||||
})
|
||||
```
|
||||
|
||||
Using Plugin B and D together, the player will be able to move freely and will be spammed with "HI", however the server will not store
|
||||
their position and other players will not see the player move.
|
||||
|
||||
#### FORMAT
|
||||
|
||||
Defition of behavior.
|
||||
- var1: Variable with value, can be changed (default: defaultValue)
|
||||
- var2 (u): Variable with value. You can change it however it will not have any effect on the defautl action (and could screw with other plugins, watch out!). U stands for unused
|
||||
|
||||
Default: What happens if this isn't cancelled.
|
||||
|
||||
Cancelled: What happens if this is cancelled and preventDefaultCancel is still false.
|
||||
|
||||
#### "move"
|
||||
|
||||
Emitted when server calculates new position for the entity (DOES NOT APPLY TO PLAYER!)
|
||||
- old (u): Where the entity came from
|
||||
- onGround (u): If the entity is on the ground
|
||||
|
||||
Default: Send entity relative-move or teleport packets to all nearby players
|
||||
|
||||
Cancelled: Set entity position to old position
|
||||
|
||||
### Methods
|
||||
|
||||
#### entity.getData(pluginName)
|
||||
|
||||
Gets object that stores data, personalized per plugin. Returns null if plugin does not exist.
|
||||
|
||||
Shortcut for: entity.pluginData[pluginName];
|
||||
|
||||
#### entity.getOthers()
|
||||
|
||||
Get every other entity other than self
|
||||
|
||||
#### entity.getOtherPlayers()
|
||||
|
||||
Gets every player other than self (all players if entity is not a player)
|
||||
|
||||
#### entity.getNearby()
|
||||
|
||||
Gets all entities nearby (within entity.viewDistance)
|
||||
|
||||
#### entity.getNearbyPlayers()
|
||||
|
||||
Gets all nearby players regardless of what client thinks
|
||||
|
||||
#### entity.nearbyPlayers()
|
||||
|
||||
Gets all nearby players that client can see
|
||||
|
||||
### Low level Methods
|
||||
|
||||
#### entity._writeOthers(packetName, packetFields)
|
||||
|
||||
Writes to all other players on server
|
||||
|
||||
#### entity._writeOthersNearby(packetName, packetFields)
|
||||
|
||||
Writes to all players within viewDistance
|
||||
|
||||
## Player
|
||||
|
||||
### Properties
|
||||
|
||||
#### player.username
|
||||
|
||||
|
|
@ -309,14 +577,6 @@ The username of the player
|
|||
|
||||
The view size of the player, for example 8 for 16x16
|
||||
|
||||
#### player.world
|
||||
|
||||
The world which the player is in.
|
||||
|
||||
#### player.nearbyPlayers
|
||||
|
||||
Nearby players.
|
||||
|
||||
### Events
|
||||
|
||||
#### "connected"
|
||||
|
|
@ -343,6 +603,176 @@ Fires when the player says `message`.
|
|||
|
||||
fires when the position changes in small amounts (walking, running, or flying)
|
||||
|
||||
### Behaviors
|
||||
|
||||
See entity "Behaviors" for more info
|
||||
|
||||
#### "move"
|
||||
|
||||
When player tries to move
|
||||
- position (u): New position player is trying to move to
|
||||
- onGround (u): Whether player thinks they're on the ground or not
|
||||
|
||||
Default: Save position/onGround and write to all nearby players
|
||||
|
||||
Cancelled: Snap back to old position
|
||||
|
||||
#### "look"
|
||||
|
||||
When player tries to look somewhere
|
||||
- yaw (u): New yaw player is looking
|
||||
- pitch (u): New pitch player is looking
|
||||
- onGround (u): If player thinks they're on the ground
|
||||
|
||||
Default: Save look directions, send to all nearby players
|
||||
|
||||
Cancelled: Snap their view back to old yaw and pitch
|
||||
|
||||
#### "chat"
|
||||
|
||||
Emitted when player tries to say something (unless they're message starts with /, then refer to "command")
|
||||
- message (u): Message player sent
|
||||
- broadcastMessage: What is put in server chat (Default: <username> message)
|
||||
|
||||
Default: Broadcasts to server their message
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "command"
|
||||
|
||||
Emitted when player starts their message with a slash
|
||||
- command: Their commands (excludes the slash)
|
||||
|
||||
Default: Handle command by command system
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "punch"
|
||||
|
||||
When player tries to punch nothing
|
||||
|
||||
Default: Send punch animation to nearby players
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "sendBlock"
|
||||
|
||||
Emitted when sending a block to a player (block changed). This is separate for every player, cancelling this for one player causes ghost blocks!
|
||||
- position: Position of the block
|
||||
- id: ID of the block
|
||||
- data: Metadata of the block
|
||||
|
||||
Default: Send block change to player.
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "sendChunk"
|
||||
|
||||
Emitted when sending a chunk to a player (loading it in)
|
||||
- x: Chunk X
|
||||
- z: Chunk Z
|
||||
- chunk: Chunk data
|
||||
|
||||
Default: Continue sending chunk to client
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "dig"
|
||||
|
||||
Emitted when any player STARTS digging (i.e. survival only)
|
||||
- position: Position of block being mined
|
||||
- block (u): Block being mined
|
||||
|
||||
Default: Allow player to start mining block, send changes in break animation to other players
|
||||
|
||||
Cancelled: Stop them from digging
|
||||
|
||||
#### "dug"
|
||||
|
||||
Emitted when a player finishes digging something (or a player in creative breaks a block)
|
||||
- position: Position of block dug
|
||||
- block (u): Block dug
|
||||
- dropBlock: Should it drop a block object (Default: false in creative, otherwise true)
|
||||
- blockDropPosition: Where block is dropped (Default: center of block)
|
||||
- blockDropWorld: World block is dropped in (Default is the world the player/block is in)
|
||||
- blockDropVelocity: The velocity the block has when dropped (Default: random)
|
||||
- blockDropId: ID of the block dropped
|
||||
- blockDropDamage: Damage of the block dropped
|
||||
- blockDropPickup: Time before user can pick up the block (Default: 0.5 seconds)
|
||||
- blockDropDeath: Time before item despawns (Default: 5 minutes)
|
||||
|
||||
Default: Save new block as air, sends to all nearby players
|
||||
|
||||
Cancelled: Send to player the block that was there
|
||||
|
||||
#### "cancelDig"
|
||||
|
||||
Emitted when a player cancels digging in the middle (i.e. survival only)
|
||||
- position: Position of block that was being mined
|
||||
- block (u): Block that was being mined
|
||||
|
||||
Default: Stop animation for all players, save stop digging
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "forceCancelDig"
|
||||
|
||||
Emitted when the server cancels a dig (currently only happens if the player mines too fast)
|
||||
- stop: Whether the digging should be cancelled because they mined too fast (Default: true)
|
||||
- start (u): Time mining started
|
||||
- time (u): How long the player has been mining
|
||||
|
||||
##### "breakAnimation"
|
||||
|
||||
Emitted when the server believes the break animation should increase (not sent by client!)
|
||||
- position: Position of block being updated
|
||||
- state: New state being changed to
|
||||
- lastState (u): Last state of block
|
||||
- start (u): When mining started
|
||||
- timePassed (u): How long between start and now
|
||||
|
||||
Default: Send animation to everyone
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "placeBlock"
|
||||
|
||||
Emitted when a player places a block
|
||||
- position: Position they're attempting to place the block
|
||||
- id: Id of block being placed
|
||||
- damage: Data of block being placed
|
||||
- reference (u): Reference block that was placed on
|
||||
- direction (u): Direction vector from reference to position
|
||||
- playSound: Which sound to play (Default: true)
|
||||
- sound: Sound to play (Default: default sound for that material)
|
||||
|
||||
Default: Place block for server and nearby players
|
||||
|
||||
Cancelled: Replace block with old block for player
|
||||
|
||||
#### "attack"
|
||||
|
||||
Emitted when a player attacks an entity
|
||||
- attackedEntity: Entity being attacked
|
||||
- playSound: Play sound (Default: true)
|
||||
- sound: Sound to play (default is game.player.hurt)
|
||||
- damage: Damage to deal (default is based off player's weapon, player's potions, attackEntity's potions, and attackedEntity armor)
|
||||
- velocity: Which way should attackedEntity move when hit
|
||||
- maxVelocity: maxVelocity from consecutive hits
|
||||
- animation: Play death/hit animation
|
||||
|
||||
Default: Damage entity, play sound, send velocity, play animation for death/hit
|
||||
|
||||
Cancelled: Nothing
|
||||
|
||||
#### "requestRespawn"
|
||||
|
||||
Emitted when a player tries to respawn
|
||||
|
||||
Default: Let them respawn
|
||||
|
||||
Cancelled: Nothing. You monster.
|
||||
|
||||
### Methods
|
||||
|
||||
#### player.login()
|
||||
|
|
@ -430,10 +860,4 @@ The internal implementation to communicate with a client
|
|||
|
||||
### Low level methods
|
||||
|
||||
#### player._writeOthers(packetName, packetFields)
|
||||
|
||||
write to other players than `player` the packet `packetName` with fields `packetFields`
|
||||
|
||||
#### player._writeOthersNearby(packetName, packetFields)
|
||||
|
||||
write to other players in same world that are within 150 blocks (see player.getNearby())
|
||||
Same as entity
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"babel-runtime": "^5.4.4",
|
||||
"emit-then": "^1.0.2",
|
||||
"minecraft-data": "0.7.0",
|
||||
"minecraft-protocol": "0.16.2",
|
||||
"mkdirp": "0.5.1",
|
||||
|
|
@ -32,10 +33,10 @@
|
|||
"prismarine-block": "0.1.0",
|
||||
"prismarine-chunk": "0.2.1",
|
||||
"prismarine-entity": "0.1.0",
|
||||
"prismarine-world": "0.3.3",
|
||||
"prismarine-world-sync": "0.1.0",
|
||||
"prismarine-item": "0.0.0",
|
||||
"prismarine-windows": "0.0.0",
|
||||
"prismarine-world": "0.3.3",
|
||||
"prismarine-world-sync": "0.1.0",
|
||||
"random-seed": "^0.2.0",
|
||||
"request-promise": "^0.4.3",
|
||||
"requireindex": "~1.0.0",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ var EventEmitter = require('events').EventEmitter;
|
|||
var path = require('path');
|
||||
var requireIndex = require('requireindex');
|
||||
var plugins = requireIndex(path.join(__dirname, 'lib', 'plugins'));
|
||||
require('emit-then').register();
|
||||
if (process.env.NODE_ENV === 'dev'){
|
||||
require('longjohn');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,25 @@
|
|||
module.exports = (obj) => {
|
||||
return async (eventName, data, func, opt) => {
|
||||
return async (eventName, data, func, cancelFunc) => {
|
||||
var hiddenCancelled = false;
|
||||
var cancelled = false;
|
||||
var cancelCount = 0;
|
||||
var cancel = (hidden) => { // Hidden shouldn't be used often but it's not hard to implement so meh
|
||||
var defaultCancel = true;
|
||||
var cancel = (dC=true, hidden=false) => { // Hidden shouldn't be used often but it's not hard to implement so meh
|
||||
if (hidden) hiddenCancelled = true;
|
||||
else {
|
||||
cancelled = true;
|
||||
cancelCount++;
|
||||
}
|
||||
defaultCancel = dC;
|
||||
}
|
||||
|
||||
await obj.emit(eventName + '_cancel', data, cancel);
|
||||
await obj.emit(eventName, data, cancelled, cancelCount);
|
||||
await obj.emitThen(eventName + '_cancel', data, cancel).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
await obj.emitThen(eventName, data, cancelled, cancelCount).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
|
||||
if (!hiddenCancelled && !cancelled) await func(data);
|
||||
if (!hiddenCancelled && !cancelled) await func(data).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
else if (cancelFunc && defaultCancel) await cancelFunc(data).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
|
||||
await obj.emit(eventName + '_done', data, cancelled);
|
||||
await obj.emitThen(eventName + '_done', data, cancelled).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
module.exports.player=function(player)
|
||||
{
|
||||
player._client.on("arm_animation", () =>
|
||||
player._writeOthersNearby("animation", {
|
||||
entityId: player.id,
|
||||
animation: 0
|
||||
}));
|
||||
player.behavior('punch', {}, () => {
|
||||
player._writeOthersNearby("animation", {
|
||||
entityId: player.id,
|
||||
animation: 0
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
player._client.on("entity_action", ({actionId} = {}) => {
|
||||
if(actionId == 3) {
|
||||
|
|
|
|||
|
|
@ -13,10 +13,17 @@ module.exports.player=function(player,serv)
|
|||
};
|
||||
|
||||
player.sendBlock = (position, blockType, blockData) => // Call from player.setBlock unless you want "local" fake blocks
|
||||
player._client.write("block_change",{
|
||||
player.behavior('sendBlock', {
|
||||
position: position,
|
||||
id: blockType,
|
||||
data: blockData
|
||||
}, ({position, id, damage}) => {
|
||||
player._client.write("block_change",{
|
||||
location:position,
|
||||
type:blockType<<4 | blockData
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
player.setBlock = (position,blockType,blockData) => serv.setBlock(player.world,position,blockType,blockData);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,19 @@ module.exports.player=function(player,serv)
|
|||
{
|
||||
player._client.on('chat', ({message} = {}) => {
|
||||
if(message[0]=="/") {
|
||||
var command = message.slice(1);
|
||||
player.handleCommand(command);
|
||||
player.behavior('command', {
|
||||
command: message.slice(1)
|
||||
}, ({command}) => {
|
||||
player.handleCommand(command);
|
||||
});
|
||||
}
|
||||
else {
|
||||
serv.broadcast('<' + player.username + '>' + ' ' + message);
|
||||
player.emit("chat",message);
|
||||
player.behavior('chat', {
|
||||
message: message,
|
||||
broadcastMessage: '<' + player.username + '>' + ' ' + message
|
||||
}, ({message, broadcast, broadcastMessage}) => {
|
||||
serv.broadcast(broadcastMessage);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,6 @@ module.exports.player=function(player) {
|
|||
|
||||
|
||||
player.handleCommand = (str) => {
|
||||
player.commands.use(str);
|
||||
player.commands.use(str).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,7 +14,12 @@ module.exports.server=function(serv) {
|
|||
serv.on('tick', (delta,count) => {
|
||||
if (!serv.doDaylightCycle) return;
|
||||
if (count % 20 == 0) {
|
||||
serv.setTime((serv.time + 20) % 24000); // Vanilla only does it every second
|
||||
serv.behavior('changeTime', {
|
||||
old: serv.time,
|
||||
newTime: serv.time + 20
|
||||
}, ({newTime}) => {
|
||||
serv.setTime((serv.time + 20) % 24000); // Vanilla only does it every second
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,48 +2,36 @@ var Vec3 = require("vec3").Vec3;
|
|||
|
||||
module.exports.player=function(player,serv)
|
||||
{
|
||||
|
||||
function cancelDig({position, block}) {
|
||||
player.sendBlock(position, block.type, block.metadata);
|
||||
}
|
||||
|
||||
player._client.on("block_dig",({location,status} = {}) => {
|
||||
var pos=new Vec3(location.x,location.y,location.z);
|
||||
player.world.getBlock(pos)
|
||||
.then(block => {
|
||||
player.behavior('digPacket', {
|
||||
position: pos,
|
||||
status: status,
|
||||
block: block
|
||||
}, ({position,status,block}) => {
|
||||
currentlyDugBlock=block;
|
||||
if(currentlyDugBlock.type==0) return;
|
||||
if(status==0 && player.gameMode!=1)
|
||||
player.behavior('dig', { // Start dig survival
|
||||
position: position,
|
||||
block: block
|
||||
}, ({position}) => {
|
||||
return startDigging(position);
|
||||
});
|
||||
else if(status==2)
|
||||
player.behavior('finishDig', { // Finish dig survival
|
||||
position: position,
|
||||
block: block
|
||||
}, ({position}) => {
|
||||
return completeDigging(position);
|
||||
});
|
||||
else if(status==1)
|
||||
player.behavior('cancelDig', { // Cancel dig survival
|
||||
position: position,
|
||||
block: block
|
||||
}, ({position}) => {
|
||||
return cancelDigging(position);
|
||||
});
|
||||
else if(status==0 && player.gameMode==1)
|
||||
player.behavior('dig', { // Start/finish dig creative
|
||||
position: position,
|
||||
block: block
|
||||
}, ({position}) => {
|
||||
return creativeDigging(position);
|
||||
});
|
||||
}
|
||||
)}
|
||||
)
|
||||
currentlyDugBlock=block;
|
||||
if(currentlyDugBlock.type==0) return;
|
||||
if(status==0 && player.gameMode!=1)
|
||||
player.behavior('dig', { // Start dig survival
|
||||
position: pos,
|
||||
block: block
|
||||
}, ({position}) => {
|
||||
return startDigging(position);
|
||||
}, cancelDig);
|
||||
else if(status==2)
|
||||
completeDigging(pos);
|
||||
else if(status==1)
|
||||
player.behavior('cancelDig', { // Cancel dig survival
|
||||
position: pos,
|
||||
block: block
|
||||
}, ({position}) => {
|
||||
return cancelDigging(position);
|
||||
});
|
||||
else if(status==0 && player.gameMode==1)
|
||||
return creativeDigging(pos);
|
||||
})
|
||||
.catch((err)=> setTimeout(() => {throw err;},0))
|
||||
});
|
||||
|
||||
|
|
@ -75,12 +63,20 @@ module.exports.player=function(player,serv)
|
|||
newDestroyState=newDestroyState>9 ? 9 : newDestroyState;
|
||||
if(newDestroyState!=lastDestroyState)
|
||||
{
|
||||
lastDestroyState=newDestroyState;
|
||||
player._writeOthersNearby("block_break_animation",{
|
||||
"entityId":currentAnimationId,
|
||||
"location":location,
|
||||
"destroyStage":newDestroyState
|
||||
});
|
||||
player.behavior('breakAnimation', {
|
||||
lastState: lastDestroyState,
|
||||
state: newDestroyState,
|
||||
start: startDigging,
|
||||
timePassed: currentDiggingTime,
|
||||
position: location
|
||||
}, ({lastState, state}) => {
|
||||
lastDestroyState=state;
|
||||
player._writeOthersNearby("block_break_animation",{
|
||||
"entityId":currentAnimationId,
|
||||
"location":location,
|
||||
"destroyStage":state
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -99,14 +95,32 @@ module.exports.player=function(player,serv)
|
|||
{
|
||||
clearInterval(animationInterval);
|
||||
var diggingTime=new Date()-startDiggingTime;
|
||||
var stop = false;
|
||||
if(expectedDiggingTime-diggingTime<100) {
|
||||
player.changeBlock(location,0,0);
|
||||
// Drop block
|
||||
serv.spawnObject(2, player.world, location.offset(0.5, 0.5, 0.5), {
|
||||
velocity: new Vec3(Math.random()*4 - 2, Math.random()*2 + 2, Math.random()*4 - 2),
|
||||
itemId: currentlyDugBlock.type,
|
||||
itemDamage: currentlyDugBlock.metadata
|
||||
});
|
||||
stop = true;
|
||||
stop = player.behavior('forceCancelDig', {
|
||||
stop: true,
|
||||
start: startDiggingTime,
|
||||
time: diggingTime
|
||||
}).stop;
|
||||
}
|
||||
if(!stop) {
|
||||
player.behavior('dug', {
|
||||
position: location,
|
||||
block: currentlyDugBlock,
|
||||
dropBlock: true,
|
||||
blockDropPosition: location.offset(0.5, 0.5, 0.5),
|
||||
blockDropWorld: player.world,
|
||||
blockDropVelocity: new Vec3(Math.random()*4 - 2, Math.random()*2 + 2, Math.random()*4 - 2),
|
||||
blockDropId: currentlyDugBlock.type,
|
||||
blockDropDamage: currentlyDugBlock.metadata,
|
||||
blockDropPickup: 500,
|
||||
blockDropDeath: 60*5*1000
|
||||
}, (data) => {
|
||||
player.changeBlock(data.position,0,0);
|
||||
console.log('dropping',data.dropBlock);
|
||||
if (data.dropBlock) dropBlock(data);
|
||||
}, cancelDig)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -117,10 +131,34 @@ module.exports.player=function(player,serv)
|
|||
}
|
||||
}
|
||||
|
||||
function dropBlock({blockDropPosition, blockDropWorld, blockDropVelocity, blockDropId, blockDropDamage, blockDropPickup, blockDropDeath}) {
|
||||
serv.spawnObject(2, blockDropWorld, blockDropPosition, {
|
||||
velocity: blockDropVelocity,
|
||||
itemId: blockDropId,
|
||||
itemDamage: blockDropDamage,
|
||||
pickupTime: blockDropPickup,
|
||||
deathTime: blockDropDeath
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function creativeDigging(location)
|
||||
{
|
||||
return player.changeBlock(location,0,0);
|
||||
player.behavior('dug', {
|
||||
position: location,
|
||||
block: currentlyDugBlock,
|
||||
dropBlock: false,
|
||||
blockDropPosition: location.offset(0.5, 0.5, 0.5),
|
||||
blockDropWorld: player.world,
|
||||
blockDropVelocity: new Vec3(Math.random()*4 - 2, Math.random()*2 + 2, Math.random()*4 - 2),
|
||||
blockDropId: currentlyDugBlock.type,
|
||||
blockDropDamage: currentlyDugBlock.metadata,
|
||||
blockDropPickup: 500,
|
||||
blockDropDeath: 60*5*1000
|
||||
}, (data) => {
|
||||
player.changeBlock(data.position,0,0);
|
||||
if (data.dropBlock) dropBlock(data);
|
||||
}, cancelDig);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -25,7 +25,7 @@ module.exports.server=function(serv,options) {
|
|||
return entity;
|
||||
};
|
||||
|
||||
serv.spawnObject = (type, world, position, {pitch=0,yaw=0,velocity=new Vec3(0,0,0),data=1,itemId,itemDamage=0}={}) => {
|
||||
serv.spawnObject = (type, world, position, {pitch=0,yaw=0,velocity=new Vec3(0,0,0),data=1,itemId,itemDamage=0,pickupTime=500,deathTime=60*1000}={}) => {
|
||||
var object = serv.initEntity('object', type, world, position.scaled(32).floored());
|
||||
object.data = data;
|
||||
object.velocity = velocity.scaled(32).floored();
|
||||
|
|
@ -35,8 +35,8 @@ module.exports.server=function(serv,options) {
|
|||
object.terminalvelocity = new Vec3(27*32, 27*32, 27*32);
|
||||
object.friction = new Vec3(15*32, 0, 15*32);
|
||||
object.size = new Vec3(0.25*32, 0.25*32, 0.25*32); // Hardcoded, will be dependent on type!
|
||||
object.deathTime = 60*1000; // 60 seconds
|
||||
object.pickupTime = 200;
|
||||
object.deathTime = deathTime;
|
||||
object.pickupTime = pickupTime;
|
||||
object.itemId = itemId;
|
||||
object.itemDamage = itemDamage;
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ module.exports.entity=function(entity,serv){
|
|||
};
|
||||
|
||||
|
||||
entity.on("positionChanged",() => {
|
||||
entity.on("move",() => {
|
||||
if(entity.position.distanceTo(entity.lastPositionPlayersUpdated)>2*32)
|
||||
entity.updateAndSpawn();
|
||||
});
|
||||
|
|
@ -259,7 +259,8 @@ module.exports.entity=function(entity,serv){
|
|||
|
||||
entity.collect = (collectEntity) => {
|
||||
if (entity.type != 'player'){
|
||||
serv.emit('error', 'Non-player entity (ttype ' + entity.type + ') cannot collect another entity')
|
||||
console.log('[ERROR] Non-player entity (type ' + entity.type + ') cannot collect another entity');
|
||||
console.log((new Error()).stack);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
var fs = require('fs');
|
||||
|
||||
module.exports.server = function(serv, settings) {
|
||||
serv.plugins = {};
|
||||
serv.pluginCount = 0;
|
||||
|
|
@ -19,15 +21,19 @@ module.exports.server = function(serv, settings) {
|
|||
}
|
||||
|
||||
for (var p in settings.plugins) {
|
||||
if (settings.plugins[p].disabled) continue;
|
||||
try {
|
||||
serv.addPlugin(p, require(p), settings.plugins[p]);
|
||||
require.resolve(p); // Check if it exists, if not do catch, otherwise jump to bottom
|
||||
} catch (err) {
|
||||
try {
|
||||
serv.addPlugin(p, require('../../plugins/' + p), settings.plugins[p]);
|
||||
try { // Throw error if cannot find plugin
|
||||
fs.accessSync('./dist/plugins/' + p);
|
||||
} catch (err) {
|
||||
throw new Error('Cannot find plugin "' + p + '"');
|
||||
}
|
||||
serv.addPlugin(p, require('../../plugins/' + p), settings.plugins[p]);
|
||||
return;
|
||||
}
|
||||
serv.addPlugin(p, require(p), settings.plugins[p]);
|
||||
}
|
||||
|
||||
for (var p in serv.plugins) {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ module.exports.player=function(player,serv)
|
|||
|
||||
player.on("disconnected",() => serv.log("[INFO]: " + player.username + ' disconnected'));
|
||||
|
||||
player.on("chat", message => serv.log("[INFO] " + '<' + player.username + '>' + ' ' + message));
|
||||
player.on("chat", ({message}) => serv.log("[INFO] " + '<' + player.username + '>' + ' ' + message));
|
||||
|
||||
player.on("kicked",(kicker,reason) =>
|
||||
serv.log(kicker.username + " kicked " + player.username + (reason ? " (" + reason + ")" : "")));
|
||||
|
|
|
|||
|
|
@ -26,15 +26,15 @@ module.exports.player=function(player,serv)
|
|||
position: placedPosition,
|
||||
reference: referencePosition,
|
||||
playSound: true,
|
||||
sound: 'dig.' + (materialToSound[blocks[heldItem.blockId].material] || 'stone')
|
||||
}, ({direction, heldItem, position, reference, playSound, sound}) => {
|
||||
sound: 'dig.' + (materialToSound[blocks[heldItem.blockId].material] || 'stone'),
|
||||
}, ({direction, heldItem, position, reference, playSound, sound, id, damage}) => {
|
||||
if (playSound) {
|
||||
serv.playSound(sound, player.world, placedPosition.clone().add(new Vec3(0.5, 0.5, 0.5)), {
|
||||
pitch: 0.8
|
||||
});
|
||||
}
|
||||
if(heldItem.blockId!=323){
|
||||
player.changeBlock(position,heldItem.blockId,heldItem.itemDamage);
|
||||
player.changeBlock(position, id, damage);
|
||||
}else if(direction==1){
|
||||
player.setBlock(position, 63, 0);
|
||||
player._client.write('open_sign_entity', {
|
||||
|
|
@ -46,6 +46,10 @@ module.exports.player=function(player,serv)
|
|||
location:position
|
||||
});
|
||||
}
|
||||
}, async () => {
|
||||
var id = await player.world.getBlockType(placedPosition);
|
||||
var damage = await player.world.getBlockData(placedPosition);
|
||||
player.sendBlock(placedPosition, id, damage);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,22 +17,31 @@ module.exports.player=function(player,serv)
|
|||
var attackedEntity = serv.entities[entityId];
|
||||
if(!attackedEntity || (attackedEntity.gameMode != 0 && attackedEntity.type == 'player')) return;
|
||||
|
||||
attackedEntity.updateHealth(attackedEntity.health - 1);
|
||||
serv.playSound('game.player.hurt', player.world, attackedEntity.position.scaled(1/32));
|
||||
player.behavior('attack', {
|
||||
attackedEntity: attackedEntity,
|
||||
sound: 'game.player.hurt',
|
||||
playSound: true,
|
||||
damage: 1,
|
||||
velocity: attackedEntity.position.minus(player.position).plus(new Vec3(0, 0.5, 0)).scaled(5),
|
||||
maxVelocity: new Vec3(4, 4, 4),
|
||||
animation: true
|
||||
}, ({attackedEntity, sound, playSound, damage, velocity, maxVelocity, animation}) => {
|
||||
attackedEntity.updateHealth(attackedEntity.health - damage);
|
||||
serv.playSound(sound, player.world, attackedEntity.position.scaled(1/32));
|
||||
|
||||
var attackVelocity = attackedEntity.position.minus(player.position).plus(new Vec3(0, 0.5, 0)).scaled(5/32);
|
||||
attackedEntity.sendVelocity(attackVelocity, new Vec3(4, 4, 4));
|
||||
attackedEntity.sendVelocity(velocity.scaled(1/32), maxVelocity);
|
||||
|
||||
if(attackedEntity.health<=0)
|
||||
attackedEntity._writeOthers('entity_status',{
|
||||
if(attackedEntity.health<=0 && animation)
|
||||
attackedEntity._writeOthers('entity_status',{
|
||||
entityId:attackedEntity.id,
|
||||
entityStatus:3
|
||||
});
|
||||
else if (animation)
|
||||
attackedEntity._writeOthers('animation',{
|
||||
entityId:attackedEntity.id,
|
||||
entityStatus:3
|
||||
animation:1
|
||||
});
|
||||
else
|
||||
attackedEntity._writeOthers('animation',{
|
||||
entityId:attackedEntity.id,
|
||||
animation:1
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
player._client.on("use_entity", ({mouse,target} = {}) => {
|
||||
|
|
|
|||
|
|
@ -2,16 +2,18 @@ module.exports.player=function(player)
|
|||
{
|
||||
player._client.on("client_command", ({payload}) => {
|
||||
if(payload == 0) {
|
||||
player._client.write("respawn",{
|
||||
dimension:0,
|
||||
difficulty:0,
|
||||
gamemode:player.gameMode,
|
||||
levelType:'default'
|
||||
player.behavior('requestRespawn', {}, () => {
|
||||
player._client.write("respawn",{
|
||||
dimension:0,
|
||||
difficulty:0,
|
||||
gamemode:player.gameMode,
|
||||
levelType:'default'
|
||||
});
|
||||
player.sendPosition();
|
||||
player.updateHealth(20);
|
||||
player.nearbyEntities=[];
|
||||
player.updateAndSpawn();
|
||||
});
|
||||
player.sendPosition();
|
||||
player.updateHealth(20);
|
||||
player.nearbyEntities=[];
|
||||
player.updateAndSpawn();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -40,30 +40,27 @@ module.exports.player=function(player,serv) {
|
|||
serv.playSound(sound, player.world, null, opt);
|
||||
};
|
||||
|
||||
player._client.on('block_place', ({location}={}) => {
|
||||
player.on('placeBlock_cancel', async ({position, reference}, cancel) => {
|
||||
if (player.crouching) return;
|
||||
var pos=new Vec3(location.x,location.y,location.z);
|
||||
player.world.getBlockType(pos).then((id) => {
|
||||
if (id != 25) return;
|
||||
if (!player.world.blockEntityData[pos.toString()]) player.world.blockEntityData[pos.toString()] = {};
|
||||
var data = player.world.blockEntityData[pos.toString()];
|
||||
if (typeof data.note == 'undefined') data.note = -1;
|
||||
data.note++;
|
||||
data.note %= 25;
|
||||
serv.playNoteBlock(data.note, player.world, pos);
|
||||
}).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
var id = await player.world.getBlockType(reference);
|
||||
if (id != 25) return;
|
||||
cancel(false);
|
||||
if (!player.world.blockEntityData[reference.toString()]) player.world.blockEntityData[reference.toString()] = {};
|
||||
var data = player.world.blockEntityData[reference.toString()];
|
||||
if (typeof data.note == 'undefined') data.note = -1;
|
||||
data.note++;
|
||||
data.note %= 25;
|
||||
serv.playNoteBlock(data.note, player.world, reference);
|
||||
});
|
||||
|
||||
player._client.on('block_dig', ({location,status} = {}) => {
|
||||
if (status != 0 || player.gameMode == 1) return;
|
||||
var pos=new Vec3(location.x,location.y,location.z);
|
||||
player.world.getBlockType(pos).then((id) => {
|
||||
if (id != 25) return;
|
||||
if (!player.world.blockEntityData[pos.toString()]) player.world.blockEntityData[pos.toString()] = {};
|
||||
var data = player.world.blockEntityData[pos.toString()];
|
||||
if (typeof data.note == 'undefined') data.note = 0;
|
||||
serv.playNoteBlock(data.not,player.world, pos, data.note);
|
||||
}).catch((err)=> setTimeout(() => {throw err;},0));
|
||||
player.on('dig_cancel', async ({position}, cancel) => {
|
||||
var id = await player.world.getBlockType(position);
|
||||
if (id != 25) return;
|
||||
cancel(false);
|
||||
if (!player.world.blockEntityData[position.toString()]) player.world.blockEntityData[position.toString()] = {};
|
||||
var data = player.world.blockEntityData[position.toString()];
|
||||
if (typeof data.note == 'undefined') data.note = 0;
|
||||
serv.playNoteBlock(data.note ,player.world, position);
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,21 +17,29 @@ module.exports.player=function(player)
|
|||
}
|
||||
function sendLook(yaw,pitch,onGround)
|
||||
{
|
||||
var convYaw=conv(yaw);
|
||||
var convPitch=conv(pitch);
|
||||
if (convYaw == player.yaw && convPitch == player.pitch) return;
|
||||
player._writeOthersNearby("entity_look", {
|
||||
entityId: player.id,
|
||||
yaw: convYaw,
|
||||
pitch: convPitch,
|
||||
player.behavior('look', {
|
||||
yaw: yaw,
|
||||
pitch: pitch,
|
||||
onGround: onGround
|
||||
});
|
||||
player.yaw = convYaw;
|
||||
player.pitch = convPitch;
|
||||
player.onGround = onGround;
|
||||
player._writeOthersNearby("entity_head_rotation", {
|
||||
entityId: player.id,
|
||||
headYaw: convYaw
|
||||
}, () => {
|
||||
var convYaw=conv(yaw);
|
||||
var convPitch=conv(pitch);
|
||||
if (convYaw == player.yaw && convPitch == player.pitch) return;
|
||||
player._writeOthersNearby("entity_look", {
|
||||
entityId: player.id,
|
||||
yaw: convYaw,
|
||||
pitch: convPitch,
|
||||
onGround: onGround
|
||||
});
|
||||
player.yaw = convYaw;
|
||||
player.pitch = convPitch;
|
||||
player.onGround = onGround;
|
||||
player._writeOthersNearby("entity_head_rotation", {
|
||||
entityId: player.id,
|
||||
headYaw: convYaw
|
||||
});
|
||||
}, () => {
|
||||
player.sendPosition();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -44,33 +52,39 @@ module.exports.player=function(player)
|
|||
});
|
||||
|
||||
function sendRelativePositionChange(newPosition, onGround) {
|
||||
if (player.position.distanceTo(new Vec3(0, 0, 0)) != 0) {
|
||||
var diff = newPosition.minus(player.position);
|
||||
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
|
||||
{
|
||||
player._writeOthersNearby('entity_teleport', {
|
||||
entityId:player.id,
|
||||
x: newPosition.x,
|
||||
y: newPosition.y,
|
||||
z: newPosition.z,
|
||||
yaw: player.yaw,
|
||||
pitch: player.pitch,
|
||||
onGround: onGround
|
||||
});
|
||||
player.behavior('move', {
|
||||
onGround: onGround,
|
||||
position: newPosition
|
||||
}, () => {
|
||||
if (player.position.distanceTo(new Vec3(0, 0, 0)) != 0) {
|
||||
var diff = newPosition.minus(player.position);
|
||||
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
|
||||
{
|
||||
player._writeOthersNearby('entity_teleport', {
|
||||
entityId:player.id,
|
||||
x: newPosition.x,
|
||||
y: newPosition.y,
|
||||
z: newPosition.z,
|
||||
yaw: player.yaw,
|
||||
pitch: player.pitch,
|
||||
onGround: onGround
|
||||
});
|
||||
}
|
||||
else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) {
|
||||
player._writeOthersNearby('rel_entity_move', {
|
||||
entityId: player.id,
|
||||
dX: diff.x,
|
||||
dY: diff.y,
|
||||
dZ: diff.z,
|
||||
onGround: onGround
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) {
|
||||
player._writeOthersNearby('rel_entity_move', {
|
||||
entityId: player.id,
|
||||
dX: diff.x,
|
||||
dY: diff.y,
|
||||
dZ: diff.z,
|
||||
onGround: onGround
|
||||
});
|
||||
}
|
||||
}
|
||||
player.position = newPosition;
|
||||
player.onGround = onGround;
|
||||
player.emit("positionChanged");
|
||||
player.position = newPosition;
|
||||
player.onGround = onGround;
|
||||
}, () => {
|
||||
player.sendPosition();
|
||||
});
|
||||
}
|
||||
|
||||
player.sendPosition = () => {
|
||||
|
|
@ -87,26 +101,31 @@ module.exports.player=function(player)
|
|||
|
||||
module.exports.entity=function(entity,serv){
|
||||
entity.sendPosition = ({oldPos,onGround}) => {
|
||||
var diff = entity.position.minus(oldPos);
|
||||
|
||||
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
|
||||
entity._writeOthersNearby('entity_teleport', {
|
||||
entityId: entity.id,
|
||||
x: entity.position.x,
|
||||
y: entity.position.y,
|
||||
z: entity.position.z,
|
||||
yaw: entity.yaw,
|
||||
pitch: entity.pitch,
|
||||
onGround: onGround
|
||||
});
|
||||
else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) serv._writeNearby('rel_entity_move', {
|
||||
entityId: entity.id,
|
||||
dX: diff.x,
|
||||
dY: diff.y,
|
||||
dZ: diff.z,
|
||||
entity.behavior('move', {
|
||||
old: oldPos,
|
||||
onGround: onGround
|
||||
}, entity);
|
||||
}, ({old,onGround}) => {
|
||||
var diff = entity.position.minus(oldPos);
|
||||
|
||||
entity.emit('positionChanged', oldPos);
|
||||
if(diff.abs().x>127 || diff.abs().y>127 || diff.abs().z>127)
|
||||
entity._writeOthersNearby('entity_teleport', {
|
||||
entityId: entity.id,
|
||||
x: entity.position.x,
|
||||
y: entity.position.y,
|
||||
z: entity.position.z,
|
||||
yaw: entity.yaw,
|
||||
pitch: entity.pitch,
|
||||
onGround: onGround
|
||||
});
|
||||
else if (diff.distanceTo(new Vec3(0, 0, 0)) != 0) serv._writeNearby('rel_entity_move', {
|
||||
entityId: entity.id,
|
||||
dX: diff.x,
|
||||
dY: diff.y,
|
||||
dZ: diff.z,
|
||||
onGround: onGround
|
||||
}, entity);
|
||||
}, () => {
|
||||
entity.position = oldPos;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
@ -70,14 +70,20 @@ module.exports.player=function(player,serv) {
|
|||
|
||||
player.sendChunk = (chunkX,chunkZ,column) =>
|
||||
{
|
||||
player._client.write('map_chunk', {
|
||||
return player.behavior('sendChunk', {
|
||||
x: chunkX,
|
||||
z: chunkZ,
|
||||
groundUp: true,
|
||||
bitMap: 0xffff,
|
||||
chunkData: column.dump()
|
||||
});
|
||||
return Promise.resolve();
|
||||
chunk: column
|
||||
}, ({x, z, chunk}) => {
|
||||
player._client.write('map_chunk', {
|
||||
x: x,
|
||||
z: z,
|
||||
groundUp: true,
|
||||
bitMap: 0xffff,
|
||||
chunkData: chunk.dump()
|
||||
});
|
||||
return Promise.resolve();
|
||||
})
|
||||
};
|
||||
|
||||
function spiral(arr)
|
||||
|
|
|
|||
Loading…
Reference in a new issue