~melchizedek6809/WolkenWelten

07ee99644692ed56f90e97b47ae65d2a1ad0a286 — Ben (X13/Arch) 13 days ago 0135639 experimental
A lot of smaller bugfixes, mostly regarding ropes/hooks
M client/src/game/character.c => client/src/game/character.c +14 -24
@@ 20,6 20,7 @@
#include "../main.h"
#include "../game/animal.h"
#include "../game/blockType.h"
#include "../game/entity.h"
#include "../game/itemDrop.h"
#include "../game/projectile.h"
#include "../game/throwable.h"


@@ 159,9 160,16 @@ static void characterUpdateHook(character *c){
		const float gl     = hookGetGoalLength(c->hook);
		const float wspeed = characterGetHookWinchS(c);
		const float maxl   = characterGetMaxHookLen(c);
		if((c->controls.y > 0) && (gl > 1.f)){
			hookSetGoalLength(c->hook,gl-wspeed);
			c->flags |= CHAR_JUMPING;
		if(c->controls.y > 0){
			if(gl > 2.f){
				hookSetGoalLength(c->hook,gl-wspeed);
				c->flags |= CHAR_JUMPING;
			}else{
				hookReturnHook(c->hook);
				c->vel = vecMul(c->vel,vecNew(0.5f,1.f,0.5));
				c->vel.y += 0.05f;
				c->flags |= CHAR_JUMPING;
			}
		}
		if((c->flags & CHAR_SNEAK) && (gl < maxl)){
			hookSetGoalLength(c->hook,gl+wspeed);


@@ 345,10 353,10 @@ void characterDie(character *c){
	if(c->flags & CHAR_SPAWNING){return;}
	if(c->flags & CHAR_NOCLIP)  {return;}
	for(int i=0;i<40;i++){
		itemDropNewP(c->pos, characterGetItemBarSlot(c,i));
		itemDropNewP(c->pos, characterGetItemBarSlot(c,i),-1);
	}
	for(int i=0;i<3;i++){
		itemDropNewP(c->pos, &c->equipment[i]);
		itemDropNewP(c->pos, &c->equipment[i],-1);
	}
	setOverlayColor(0xFF000000,0);
	characterInit(c);


@@ 414,25 422,7 @@ static void characterGoStepUp(character *c){
}

static float characterBlockRepulsion(character *c, float *vel){
	(void)c;
	int ret = 0;
	vec blockPos;
	const u8 b = characterCollisionBlock(c->pos,&blockPos);
	if(b == 0){return 0;}

	float strength = *vel;
	const int blockDamage = fabsf(strength) * 4192.f;
	const int blockHealth = blockTypeGetHealth(b);
	if(blockDamage > blockHealth){
		worldMine(blockPos.x,blockPos.y,blockPos.z);
		strength = strength * ((float)blockHealth / (float)blockDamage);
		fxBlockBreak(blockPos,b,0);
	}

	if(fabsf(strength) > 0.1f){ret += (int)(fabsf(strength)*512.f);}
	*vel += strength* -1.3f;

	return ret;
	return blockRepulsion(c->pos,vel,80.f,characterCollisionBlock);
}

static int characterPhysics(character *c){

M client/src/game/grenade.c => client/src/game/grenade.c +1 -1
@@ 85,7 85,7 @@ void grenadeUpdateFromServer(const packet *p){
	if(index >= grenadeCount){return;}

	if(grenadeList[index].ent == NULL){
		grenadeList[index].ent = entityNew(vecZero(),vecZero());
		grenadeList[index].ent = entityNew(vecZero(),vecZero(),grenadeList[index].pwr * 3.f);
		grenadeList[index].ent->eMesh = meshBomb;
	}
	grenadeList[index].ent->pos = vecNewP(&p->v.f[1]);

M client/src/game/itemDrop.c => client/src/game/itemDrop.c +4 -2
@@ 34,7 34,8 @@ void itemDropNewC(const character *chr,const item *itm){
	msgItemDropNew(-1,vecAdd(pos,vecMulS(vel,100)),vel,itm);
}

void itemDropNewP(const vec pos,const item *itm){
void itemDropNewP(const vec pos,const item *itm, i16 IDPlayer){
	(void)IDPlayer;
	if(itemIsEmpty(itm)){return;}
	const vec vel = vecMulS(vecRngAbs(),0.03);
	msgItemDropNew(-1,pos,vel,itm);


@@ 101,10 102,11 @@ void itemDropUpdateFromServer(const packet *p){
	const vec idpos = vecNewP(&p->v.f[2]);
	const vec idvel = vecNewP(&p->v.f[5]);
	if(itemDropList[d].ent == NULL){
		itemDropList[d].ent     = entityNew(idpos,vecZero());
		itemDropList[d].ent     = entityNew(idpos,vecZero(),itemGetWeight(&itemDropList[d].itm));
		itemDropList[d].aniStep = rngValM(1024);
		itemDropList[d].player = -1;
	}
	itemDropList[d].player     = p->v.i16[16];

	itemDropList[d].ent->eMesh = itemGetMesh(&itemDropList[d].itm);
	itemDropList[d].ent->pos   = idpos;

M client/src/misc/lisp.c => client/src/misc/lisp.c +9 -9
@@ 783,15 783,15 @@ static void lispAddClientNFuncs(lClosure *c){
	lAddNativeFunc(c,"aiming?",        "()",                "Predicate that evaluates to #t when the player is aiming.",      wwlnfAimingPred);
	lAddNativeFunc(c,"throwing?",      "()",                "Predicate that evaluates to #t when the player is throw-aiming.",wwlnfThrowingPred);
	lAddNativeFunc(c,"throw-item",     "(flags &force &amount)", "Throw the currently held item with FLAGS, &FORCE=0.1 and &AMOUNT=1",wwlnfThrowItem);
	lAddNativeFunc(c,"player-drop-item!","(slot)",          "Throw a single item from SLOT in front of the player" ,wwlnfDropItem);
	lAddNativeFunc(c,"try-to-shoot",   "(cd ammo)",         "Try to shoot and cooldown for CD and use AMMO bullets"          ,wwlnfTryToShoot);
	lAddNativeFunc(c,"beamblast",      "(size damage hits-left)", "Calls cFunc beamblast",                                   wwlnfBeamblast);
	lAddNativeFunc(c,"projectile",     "(&type &num)",      "Fire &NUM=1 projectiles of &TYPE=0",                            wwlnfProjectile);
	lAddNativeFunc(c,"fire-new",       "(pos &strength)",   "Create/Grow a fire at POS with &STRENGTH=8",                    wwlnfFireNew);
	lAddNativeFunc(c,"toggle-inventory!","()",              "Toggle the inveotory",                                          wwlnfToggleInventory);
	lAddNativeFunc(c,"widget-focus-on-game?","()",          "Return #t if the game is focused and not some menu",            wwlnfGuiFocusOnGame);
	lAddNativeFunc(c,"draw-boundaries", "()",                "Return the current boundary drawing style",                    wwlnfDrawBoundariesGet);
	lAddNativeFunc(c,"draw-boundaries!","(v)",               "Set the current boundary drawing style",                       wwlnfDrawBoundariesSet);
	lAddNativeFunc(c,"player-drop-item!","(slot)",          "Throw a single item from SLOT in front of the player",           wwlnfDropItem);
	lAddNativeFunc(c,"try-to-shoot",   "(cd ammo)",         "Try to shoot and cooldown for CD and use AMMO bullets",          wwlnfTryToShoot);
	lAddNativeFunc(c,"beamblast",      "(size damage hits-left)", "Calls cFunc beamblast",                                    wwlnfBeamblast);
	lAddNativeFunc(c,"projectile",     "(&type &num)",      "Fire &NUM=1 projectiles of &TYPE=0",                             wwlnfProjectile);
	lAddNativeFunc(c,"fire-new",       "(pos &strength)",   "Create/Grow a fire at POS with &STRENGTH=8",                     wwlnfFireNew);
	lAddNativeFunc(c,"toggle-inventory!","()",              "Toggle the inveotory",                                           wwlnfToggleInventory);
	lAddNativeFunc(c,"widget-focus-on-game?","()",          "Return #t if the game is focused and not some menu",             wwlnfGuiFocusOnGame);
	lAddNativeFunc(c,"draw-boundaries", "()",                "Return the current boundary drawing style",                     wwlnfDrawBoundariesGet);
	lAddNativeFunc(c,"draw-boundaries!","(v)",               "Set the current boundary drawing style",                        wwlnfDrawBoundariesSet);
}

void lispInit(){

M client/src/network/client.c => client/src/network/client.c +6 -0
@@ 343,6 343,7 @@ void clientParsePacket(const packet *p){
	case msgtDyingMsg:
	case msgtRequestSpawnPos:
	case msgtChungusUnsub:
	case msgtBeingMove:
	case msgtItemDropNew:
	case msgtItemDropPickup:
	case msgtItemDropBounce:


@@ 437,3 438,8 @@ void clientFree(){
	closeSingleplayerServer();
	openMainMenu();
}

int getClientByCharacter(const character *c){
	(void)c;
	return -1;
}

M client/src/nujel/input.nuj => client/src/nujel/input.nuj +3 -3
@@ 6,7 6,7 @@
[def input-tick]

[let []
	[def did-primary #f]
	[def did-primary #f]e
	[def did-throw #f]
	[def throw-start 0]



@@ 67,7 67,7 @@

		[when [not did-primary] [player-stop-mining!]]
		[when did-primary [set! did-primary #f]]
		[when [and [not did-throw] [> throw-start 0]] [player-do-throw! [- [time-milliseconds] throw-start]]]
		[when did-throw [set! did-throw #f]]
		[when [and [not did-throw] [ineq? throw-start 0]] [player-do-throw! [- [time-milliseconds] throw-start]]]
		[set! did-throw #f]
	]]
]

M client/src/voxel/bigchungus.c => client/src/voxel/bigchungus.c +10 -0
@@ 307,6 307,16 @@ void worldMine(int x, int y, int z){
	}
}

void worldBreak(int x, int y, int z){
	const u8 b = worldGetB(x,y,z);
	msgMineBlock(x,y,z,b,1);
	if((b == I_Grass) || (b == I_Dry_Grass)){
		worldSetB(x,y,z,I_Dirt);
	}else{
		worldSetB(x,y,z,0);
	}
}

void worldBoxMine(int x, int y, int z, int w, int h, int d){
	for(int cx=0;cx<w;cx++){
	for(int cy=0;cy<h;cy++){

M client/src/voxel/bigchungus.h => client/src/voxel/bigchungus.h +1 -0
@@ 17,6 17,7 @@ chunk   *worldTryChunk         (int x, int y, int z);
bool     worldSetB             (int x, int y, int z, u8 block);
void     worldSetChungusLoaded (int x, int y, int z);
void     worldMine             (int x, int y, int z);
void     worldBreak            (int x, int y, int z);
void     worldBoxMine          (int x, int y, int z, int w, int h, int d);
int      checkCollision        (int x, int y, int z);
bool     worldIsLoaded         (int x, int y, int z);

M common/src/animals/bunny.c => common/src/animals/bunny.c +3 -3
@@ 283,7 283,7 @@ static void animalSEat(animal *e,int stateChange[16]){

static void animalDoPoop(animal *e,int stateChange[16]){
	item ipoop = itemNew(I_Poop,1);
	itemDropNewP(e->pos, &ipoop);
	itemDropNewP(e->pos, &ipoop,-1);
	stateChange[ANIMAL_S_FLEE] += 256;
}



@@ 427,6 427,6 @@ void animalThinkBunny(animal *e){
void animalRDieBunny(animal *e){
	item mdrop = itemNew(I_Meat,rngValMM(2,4));
	item fdrop = itemNew(I_Fur, rngValMM(1,2));
	itemDropNewP(e->pos,&mdrop);
	itemDropNewP(e->pos,&fdrop);
	itemDropNewP(e->pos,&mdrop,-1);
	itemDropNewP(e->pos,&fdrop,-1);
}

M common/src/animals/guardian.c => common/src/animals/guardian.c +1 -1
@@ 123,7 123,7 @@ void animalThinkGuardian(animal *e){

void animalRDieGuardian(animal *e){
	item drop = itemNew(I_Crystalbullet,rngValMM(20,40));
	itemDropNewP(e->pos,&drop);
	itemDropNewP(e->pos,&drop,-1);
}

void animalRBurnGuardian(animal *e){

M common/src/animals/werebunny.c => common/src/animals/werebunny.c +3 -3
@@ 293,7 293,7 @@ static void animalSEat(animal *e,int stateChange[16]){

static void animalDoPoop(animal *e,int stateChange[16]){
	item ipoop = itemNew(I_Poop,1);
	itemDropNewP(e->pos, &ipoop);
	itemDropNewP(e->pos, &ipoop,-1);
	stateChange[ANIMAL_S_FLEE] += 256;
}



@@ 429,6 429,6 @@ void animalThinkWerebunny(animal *e){
void animalRDieWerebunny(animal *e){
	item mdrop = itemNew(I_Meat,rngValMM(4,6));
	item fdrop = itemNew(I_Fur, rngValMM(3,4));
	itemDropNewP(e->pos,&mdrop);
	itemDropNewP(e->pos,&fdrop);
	itemDropNewP(e->pos,&mdrop,-1);
	itemDropNewP(e->pos,&fdrop,-1);
}

M common/src/game/animal.c => common/src/game/animal.c +43 -13
@@ 23,6 23,7 @@
#include "../game/being.h"
#include "../game/blockType.h"
#include "../game/character.h"
#include "../game/entity.h"
#include "../game/fire.h"
#include "../game/rope.h"
#include "../game/time.h"


@@ 101,6 102,7 @@ void animalDel(uint i){
		printf("AnimalDel: type==0!!!\n");
		return;
	}
	animalList[i].pos      = vecNOne();
	animalList[i].bl       = NULL;
	animalList[i].type     = 0;
	animalList[i].nextFree = animalFirstFree;


@@ 135,6 137,21 @@ u32 animalCollision(const vec c){
	return col;
}

u8 animalCollisionBlock(const vec c, vec *retPos){
	u8 b;
	if((b = worldGetB(c.x-0.3f,c.y     ,c.z     ))){*retPos = vecNew(c.x-0.3f,c.y,c.z); return b;}
	if((b = worldGetB(c.x+0.3f,c.y     ,c.z     ))){*retPos = vecNew(c.x+0.3f,c.y,c.z); return b;}
	if((b = worldGetB(c.x     ,c.y     ,c.z-0.3f))){*retPos = vecNew(c.x,c.y,c.z-0.3f); return b;}
	if((b = worldGetB(c.x     ,c.y     ,c.z+0.3f))){*retPos = vecNew(c.x,c.y,c.z+0.3f); return b;}
	if((b = worldGetB(c.x     ,c.y+0.5f,c.z     ))){*retPos = vecNew(c.x,c.y+0.5f,c.z); return b;}
	if((b = worldGetB(c.x     ,c.y-1.0f,c.z     ))){*retPos = vecNew(c.x,c.y-1.0f,c.z); return b;}
	return 0;
}

static float animalBlockRepulsion(animal *c, float *vel){
	return blockRepulsion(c->pos,vel,animalGetWeight(c),animalCollisionBlock);
}

void animalCheckForHillOrCliff(animal *e){
	const vec cFDir = vecAdd(e->pos,vecMulS(vecNorm(vecMul(e->vel,vecNew(1,0,1))),0.5f));
	const u8 cb     = worldGetB(cFDir.x, cFDir.y, cFDir.z);


@@ 228,36 245,35 @@ int animalUpdate(animal *e){
	if(col){ e->flags |= ANIMAL_COLLIDE; }

	if((col&0x110) && (e->vel.x < 0.f)){
		if(e->vel.x < -0.05f){ ret += (int)(fabsf(e->vel.x)*ANIMAL_FALL_DMG); }
		if(e->vel.x < -0.05f){ ret += animalBlockRepulsion(e,&e->pos.x); }
		e->pos.x = MAX(e->pos.x,floor(e->pos.x)+0.3f);
		e->vel.x = e->vel.x*-0.3f;
	}
	if((col&0x220) && (e->vel.x > 0.f)){
		if(e->vel.x >  0.05f){ ret += (int)(fabsf(e->vel.x)*ANIMAL_FALL_DMG); }
		if(e->vel.x >  0.05f){ ret += animalBlockRepulsion(e,&e->pos.x); }
		e->pos.x = MIN(e->pos.x,floorf(e->pos.x)+0.7f);
		e->vel.x = e->vel.x*-0.3f;
	}
	if((col&0x880) && (e->vel.z > 0.f)){
		if(e->vel.z >  0.05f){ ret += (int)(fabsf(e->vel.z)*ANIMAL_FALL_DMG); }
		if(e->vel.z >  0.05f){ ret += animalBlockRepulsion(e,&e->pos.z); }
		e->pos.z = MIN(e->pos.z,floorf(e->pos.z)+0.7f);
		e->vel.z = e->vel.z*-0.3f;
	}
	if((col&0x440) && (e->vel.z < 0.f)){
		if(e->vel.z < -0.05f){ ret += (int)(fabsf(e->vel.z)*ANIMAL_FALL_DMG); }
		if(e->vel.z < -0.05f){ ret += animalBlockRepulsion(e,&e->pos.z); }
		e->pos.z = MAX(e->pos.z,floorf(e->pos.z)+0.3f);
		e->vel.z = e->vel.z*-0.3f;
	}
	if((col&0x0F0) && (e->vel.y > 0.f)){
		if(e->vel.y >  0.05f){ ret += (int)(fabsf(e->vel.y)*ANIMAL_FALL_DMG); }
		if(e->vel.y >  0.05f){ ret += animalBlockRepulsion(e,&e->pos.y); }
		e->pos.y = MIN(e->pos.y,floorf(e->pos.y)+0.5f);
		e->vel.y = e->vel.y*-0.3f;
	}
	if((col&0x00F) && (e->vel.y < 0.f)){
		e->flags &= ~ANIMAL_FALLING;
		if(e->vel.y < -0.05f){
			ret += (int)(fabsf(e->vel.y)*ANIMAL_FALL_DMG);
		if(e->vel.y < -0.15f){
			ret += animalBlockRepulsion(e,&e->vel.y);
		}else if(e->vel.y > -0.04f){
			e->vel = vecMul(e->vel,vecNew(0.97f,0,0.97f));
		}
		if(fabsf(e->vel.y) < 0.001f){
			e->pos.y = floorf(e->pos.y)+1.0f;
		}
		e->vel = vecMul(e->vel,vecNew(0.97f,0,0.97f));
	}
	return ret;
}


@@ 304,6 320,20 @@ int animalGetMaxHealth (const animal *e){
	return 0;
}

float animalGetWeight (const animal *e){
	switch((animalType)e->type){
	case animalUnused:
		return 2.f;
	case animalBunny:
		return 2.f;
	case animalGuardian:
		return 100.f;
	case animalWerebunny:
		return 6.f;
	}
	return 0;
}

animal *animalGetByBeing(being b){
	const uint i = beingID(b);
	if(beingType(b) != BEING_ANIMAL){ return NULL; }

M common/src/game/animal.h => common/src/game/animal.h +1 -0
@@ 19,6 19,7 @@ void        animalReset            (      animal *e);
float       animalDistance         (const animal *e,const character *c);
const char *animalGetStateName     (const animal *e);
int         animalGetMaxHealth     (const animal *e);
float        animalGetWeight        (const animal *e);
int         animalUpdate           (      animal *e);
void        animalThink            (      animal *e);
float       animalClosestAnimal    (const animal *e, animal **cAnim, int typeFilter, uint flagsMask, uint flagsCompare);

M common/src/game/entity.c => common/src/game/entity.c +72 -24
@@ 17,6 17,8 @@

#include "entity.h"

#include "../game/blockType.h"
#include "../misc/effects.h"
#include "../misc/profiling.h"
#include "../world/world.h"



@@ 31,7 33,7 @@ void entityReset(entity *e){
	memset(e,0,sizeof(entity));
}

entity *entityNew(vec pos, vec rot){
entity *entityNew(vec pos, vec rot, float weight){
	entity *e = NULL;
	if(entityFirstFree == NULL){
		e = &entityList[entityCount++];


@@ 46,6 48,7 @@ entity *entityNew(vec pos, vec rot){

	e->pos = pos;
	e->rot = rot;
	e->weight = weight;

	return e;
}


@@ 72,16 75,14 @@ u32 entityCollision(const vec c){
	return col;
}

u8 entityGetBlockCollision(const entity *e){
	if(e == NULL){return 0;}
	const vec c = e->pos;
u8 entityCollisionBlock(const vec c, vec *retPos){
	u8 b;
	if((b = worldGetB(c.x-0.3f,c.y     ,c.z     ))){return b;}
	if((b = worldGetB(c.x+0.3f,c.y     ,c.z     ))){return b;}
	if((b = worldGetB(c.x     ,c.y     ,c.z-0.3f))){return b;}
	if((b = worldGetB(c.x     ,c.y     ,c.z+0.3f))){return b;}
	if((b = worldGetB(c.x     ,c.y+0.5f,c.z     ))){return b;}
	if((b = worldGetB(c.x     ,c.y-0.5f,c.z     ))){return b;}
	if((b = worldGetB(c.x-0.3f,c.y     ,c.z     ))){*retPos = vecNew(c.x-0.3f,c.y,c.z); return b;}
	if((b = worldGetB(c.x+0.3f,c.y     ,c.z     ))){*retPos = vecNew(c.x+0.3f,c.y,c.z); return b;}
	if((b = worldGetB(c.x     ,c.y     ,c.z-0.3f))){*retPos = vecNew(c.x,c.y,c.z-0.3f); return b;}
	if((b = worldGetB(c.x     ,c.y     ,c.z+0.3f))){*retPos = vecNew(c.x,c.y,c.z+0.3f); return b;}
	if((b = worldGetB(c.x     ,c.y+0.5f,c.z     ))){*retPos = vecNew(c.x,c.y+0.5f,c.z); return b;}
	if((b = worldGetB(c.x     ,c.y-0.5f,c.z     ))){*retPos = vecNew(c.x,c.y-0.5f,c.z); return b;}
	return 0;
}



@@ 92,6 93,10 @@ void entityUpdateCurChungus(entity *e){
	e->curChungus = worldTryChungus(cx,cy,cz);
}

static float entityBlockRepulsion(entity *c, float *vel){
	return blockRepulsion(c->pos,vel,c->weight,entityCollisionBlock);
}

int entityUpdate(entity *e){
	int ret=0;
	u32 col;


@@ 126,42 131,60 @@ int entityUpdate(entity *e){
		return 0;
	}
	if((col&0x110) && (e->vel.x < 0.f)){
		if(e->vel.x < -0.1f){ ret += (int)(fabsf(e->vel.x)*128.f); }
		if(e->vel.x < -0.1f){
			ret += entityBlockRepulsion(e,&e->vel.x);
		} else {
			e->vel.x *= -0.97f;
		}
		e->pos.x = MAX(e->pos.x,floor(e->pos.x)+0.3f);
		e->vel.x = e->vel.x*-0.3f;
	}
	if((col&0x220) && (e->vel.x > 0.f)){
		if(e->vel.x >  0.1f){ ret += (int)(fabsf(e->vel.x)*128.f); }
		if(e->vel.x >  0.1f){
			ret += entityBlockRepulsion(e,&e->vel.x);
		}else{
			e->vel.x *= -0.97f;
		}
		e->pos.x = MIN(e->pos.x,floorf(e->pos.x)+0.7f);
		e->vel.x = e->vel.x*-0.3f;
	}
	if((col&0x880) && (e->vel.z > 0.f)){
		if(e->vel.z >  0.1f){ ret += (int)(fabsf(e->vel.z)*128.f); }
		if(e->vel.z >  0.1f){
			ret += entityBlockRepulsion(e,&e->vel.z);
		} else {
			e->vel.z *= -0.97f;
		}
		e->pos.z = MIN(e->pos.z,floorf(e->pos.z)+0.7f);
		e->vel.z = e->vel.z*-0.3f;
	}
	if((col&0x440) && (e->vel.z < 0.f)){
		if(e->vel.z < -0.1f){ ret += (int)(fabsf(e->vel.z)*128.f); }
		if(e->vel.z < -0.1f){
			ret += entityBlockRepulsion(e,&e->vel.z);
		}else{
			e->vel.z *= -0.97f;
		}
		e->pos.z = MAX(e->pos.z,floorf(e->pos.z)+0.3f);
		e->vel.z = e->vel.z*-0.3f;
	}
	if((col&0x0F0) && (e->vel.y > 0.f)){
		if(e->vel.y >  0.1f){ ret += (int)(fabsf(e->vel.y)*128.f); }
		e->pos.y = MIN(e->pos.y,floorf(e->pos.y)+0.5f);
		e->vel.y = e->vel.y*-0.3f;
		e->pos.y = MIN(e->pos.y,floorf(e->pos.y)+0.3f); // Still needed?
		if(e->vel.y >  0.1f){
			ret += entityBlockRepulsion(e,&e->vel.y);
		}else{
			e->vel.y *= 0.97f;
		}
	}
	if((col&0x00F) && (e->vel.y < 0.f)){
		e->flags &= ~ENTITY_FALLING;
		if(e->vel.y < -0.15f){
			e->yoff = -0.8f;
			ret += (int)(fabsf(e->vel.y)*128.f);
			ret += entityBlockRepulsion(e,&e->vel.y);
		}else if(e->vel.y < -0.07f){
			e->yoff += -0.4f;
		}else if(e->vel.y < -0.04f){
			e->yoff += -0.2f;
		}else{
			e->vel = vecMul(e->vel,vecNew(0.93f,0,0.93f));
		}
		if(fabsf(e->vel.y) < 0.001f){ // Still needed?
			e->pos.y = floorf(e->pos.y)+.5f;
		}
		e->vel = vecMul(e->vel,vecNew(0.93f,0,0.93f));
		e->vel.y = 0.001f;
	}
	col = entityCollision(e->pos);
	if((col & 0xFFF) == 0xFFF){


@@ 221,3 244,28 @@ entity *entityGetByBeing(being b){
	if(i >= entityCount)             { return NULL; }
	return &entityList[i];
}

float blockRepulsion(const vec pos, float *vel, float weight, u8 (*colFunc)(const vec,vec *)){
	int ret = 0;
	vec blockPos;
	const u8 b = colFunc(pos,&blockPos);
	if(b == 0){return 0;}

	float strength = *vel;
	const int blockDamage = fabsf(strength) * weight * 50.f;
	const int blockHealth = blockTypeGetHealth(b);
	if(blockDamage > blockHealth){
		worldBreak(blockPos.x,blockPos.y,blockPos.z);
		strength = strength * ((float)blockHealth / (float)blockDamage);
		fxBlockBreak(blockPos,b,0);
	}

	if(fabsf(strength) > 0.1f){ret += (int)(fabsf(strength)*512.f);}
	if(strength < 1.f){
		*vel = 0;
	}else{
		*vel += strength* -1.3f;
	}

	return ret;
}

M common/src/game/entity.h => common/src/game/entity.h +3 -2
@@ 5,14 5,15 @@
extern entity entityList[1<<14];
extern uint   entityCount;

entity  *entityNew              (const vec pos, const vec rot);
entity  *entityNew              (const vec pos, const vec rot, float weight);
void     entityFree             (      entity *e);
void     entityReset            (      entity *e);
float    entityDistance         (const entity *e,const character *c);
int      entityUpdate           (      entity *e);
void     entityUpdateCurChungus (      entity *e);
u32      entityCollision        (const vec c);
u8       entityGetBlockCollision(const entity *e);
u8       entityCollisionBlock   (const vec pos, vec *retPos);
void     entityUpdateAll        ();
float    blockRepulsion         (const vec pos, float *vel, float weight, u8 (*colFunc)(const vec,vec *));

uint   lineOfSightBlockCount    (const vec a, const vec b, uint maxB);

M common/src/game/hook.c => common/src/game/hook.c +4 -4
@@ 51,7 51,7 @@ hook *hookNew(character *p){
	if(characterGetMaxHookLen(p) > 128.f){flags |= ROPE_TEX_CHAIN;}

	ghk->parent       = p;
	ghk->ent          = entityNew(vecAdd(vecNew(0,1,0),p->pos),vecNew(-p->rot.yaw,-p->rot.pitch-90.f,p->rot.roll));
	ghk->ent          = entityNew(vecAdd(vecNew(0,1,0),p->pos),vecNew(-p->rot.yaw,-p->rot.pitch-90.f,p->rot.roll),3000.f);
	ghk->ent->vel     = vecAdd(vecMulS(vecDegToVec(p->rot),1.3f),p->vel);
	ghk->ent->eMesh   = meshHook;
	ghk->ent->flags   = ENTITY_NOREPULSION;


@@ 134,7 134,7 @@ bool hookUpdate(hook *ghk){
			if(b){ fxBlockBreak(vecFloor(ghk->ent->pos),b,0);}
		}else{
			being closest = beingClosest(ghk->ent->pos,1.f);
			if((closest != 0) && (closest != characterGetBeing(ghk->parent))){
			if((closest != 0) && (closest != characterGetBeing(ghk->parent)) && (closest != ghk->attached)){
				ghk->ent->vel     = vecZero();
				ghk->ent->flags  |= ENTITY_NOCLIP;
				ghk->hooked       = true;


@@ 144,8 144,8 @@ bool hookUpdate(hook *ghk){
				ghk->rope->a      = closest;
				ghk->ent->pos     = beingGetPos(closest);
				ghk->rope->flags |= ROPE_DIRTY;
				//sfxPlay(sfxHookHit,1.f);
				//sfxPlay(sfxUngh,1.f);
				sfxPlay(sfxHookHit,1.f);
				sfxPlay(sfxUngh,1.f);
				fxBlockBreak(ghk->ent->pos,2,0);
				sfxLoop(sfxHookRope,0.f);
			}else if(!ghk->hooked && !ghk->returning){

M common/src/game/itemDrop.c => common/src/game/itemDrop.c +1 -1
@@ 33,7 33,7 @@ int      itemDropFirstFree = -1;

void itemDropEmptyMsg(uint c, uint i){
	item itm = itemEmpty();
	msgItemDropUpdate(c,vecNOne(),vecZero(),&itm,i,itemDropCount);
	msgItemDropUpdate(c,vecNOne(),vecZero(),&itm,i,itemDropCount,-1);
}

itemDrop *itemDropGetByBeing(being b){

M common/src/game/itemDrop.h => common/src/game/itemDrop.h +2 -2
@@ 6,12 6,12 @@ extern uint     itemDropCount;
extern int      itemDropFirstFree;

void itemDropNewC             (const character *chr,const item *itm);
void itemDropNewP             (const vec pos,const item *itm);
void itemDropNewP             (const vec pos,const item *itm, i16 IDPlayer);
void itemDropDel              (uint d);
void itemDropDelChungus       (const chungus *c);
void itemDropUpdateAll        ();
void itemDropEmptyMsg         (uint c, uint i);
void itemDropNewP             (const vec pos,const item *itm);
void itemDropNewP             (const vec pos,const item *itm, i16 IDPlayer);

itemDrop *itemDropGetByBeing  (being b);
being     itemDropGetBeing    (const itemDrop *id);

M common/src/game/rope.c => common/src/game/rope.c +8 -4
@@ 19,6 19,7 @@

#include "../game/being.h"
#include "../game/entity.h"
#include "../network/messages.h"

#include <string.h>



@@ 60,18 61,21 @@ static void ropePullTowards(being a, being b, float goalLen, float mul){
	vec velAdd = vecZero();
	if(((d.x > 0) && !((col & 0x110))) || ((d.x < 0) && !((col & 0x220)))){
		posAdd.x = d.x * -0.6f * mul;
		velAdd.x = d.x * -0.2f * mul;
		velAdd.x = MINMAX(d.x * -0.1f * mul,-0.01,0.01);
	}
	if(((d.z > 0) && !((col & 0x440))) || ((d.z < 0) && !((col & 0x880)))){
		posAdd.z = d.z * -0.6f * mul;
		velAdd.z = d.z * -0.2f * mul;
		velAdd.z = MINMAX(d.z * -0.1f * mul,-0.01,0.01);
	}
	if(((d.y > 0) && !((col & 0x00F))) || ((d.y < 0) && !((col & 0x0F0)))){
		posAdd.y = d.y * -0.6f * mul;
		velAdd.y = d.y * -0.2f * mul;
		velAdd.y = MINMAX(d.y * -0.1f * mul,-0.01,0.01);
	}
	beingAddPos(b,posAdd);
	beingAddVel(b,velAdd);
	if(isClient && beingType(b) == BEING_ANIMAL){
		msgBeingMove(b,posAdd,velAdd);
	}
}

static void ropeUpdate(rope *r){


@@ 94,8 98,8 @@ static void ropeUpdate(rope *r){
		bm = 0.f;
	}

	ropePullTowards(r->a,r->b,r->length,bm);
	ropePullTowards(r->b,r->a,r->length,am);
	ropePullTowards(r->a,r->b,r->length,bm);
}

void  ropeUpdateAll(){

M common/src/game/throwable.c => common/src/game/throwable.c +8 -3
@@ 152,7 152,7 @@ void throwableRecvUpdate(const packet *p){
	a->thrower    = p->v.u32[ 3];

	if(a->ent == NULL){
		a->ent = entityNew(vecNewP(&p->v.f[ 4]),vecZero());
		a->ent = entityNew(vecNewP(&p->v.f[ 4]),vecZero(),itemGetWeight(&a->itm));
		if(isClient){
			a->ent->eMesh = itemGetMesh(&a->itm);
		}


@@ 169,11 169,14 @@ void throwableRecvUpdate(const packet *p){
	}
}

#include <stdio.h>
int getClientByCharacter(const character *c);
static void throwableUpdate(throwable *t){
	if(t->ent == NULL){return;}
	entityUpdate(t->ent);
	if((t->flags & THROWABLE_PIERCE) && (t->ent->flags & ENTITY_COLLIDE)){
		const u8 b = entityGetBlockCollision(t->ent);
		vec retPos;
		const u8 b = entityCollisionBlock(t->ent->pos,&retPos);
		const blockCategory cat = blockTypeGetCat(b);
		if(cat != STONE){
			t->ent->flags |= ENTITY_NOCLIP;


@@ 204,7 207,9 @@ static void throwableUpdate(throwable *t){
		}
	}
	if(!isClient && !(t->ent->flags & ENTITY_NOCLIP) && (t->ent->flags & ENTITY_COLLIDE) && (vecAbsSum(t->ent->vel) < 0.01f)){
		itemDropNewP(t->ent->pos,&t->itm);
		const i16 clientID = getClientByCharacter(characterGetByBeing(t->thrower));
		printf("clientID: %i\n",clientID);
		itemDropNewP(t->ent->pos,&t->itm,clientID);
		t->itm.amount = 0;
		t->itm.ID = 0;
		throwableSendUpdate(-1,t - throwableList);

M common/src/game_structs.h => common/src/game_structs.h +1 -0
@@ 93,6 93,7 @@ struct beingList {
typedef struct {
	vec pos,vel,rot;
	float yoff;
	float weight;
	u32 flags;

	mesh    *eMesh;

M common/src/misc/lisp.c => common/src/misc/lisp.c +2 -2
@@ 100,7 100,7 @@ static lVal *wwlnfItemDropNew(lClosure *c, lVal *v){

	if((pos.x < 0.f) || (pos.y < 0.f) || (pos.z < 0.f) || (id <= 0) || (amt <= 0)){return NULL;}
	item itm = itemNew(id,amt);
	itemDropNewP(pos,&itm);
	itemDropNewP(pos,&itm,-1);
	return NULL;
}



@@ 191,7 191,7 @@ lVal *lispCallFuncVII(const char *symbol,const vec va, int ib , int ic){
}

void lispDefineID(const char *prefix, const char *symbol, int val){
	char lName[16];
	char lName[sizeof(lSymbol)];
	int len = sizeof(lName);

	memset(lName,0,sizeof(lName));

M common/src/network/messages.c => common/src/network/messages.c +24 -2
@@ 153,6 153,23 @@ void msgItemDropNew(int c, const vec pos, const vec vel, const item *itm){
	packetQueue(p,msgtItemDropNew,8*4,c);
}

void msgBeingMove(being b, vec dpos, vec dvel){
	packet *p = &packetBuffer;

	p->v.u32[0] = b;

	p->v.f[1] = dpos.x;
	p->v.f[2] = dpos.y;
	p->v.f[3] = dpos.z;

	p->v.f[4] = dvel.x;
	p->v.f[5] = dvel.y;
	p->v.f[6] = dvel.z;


	packetQueue(p,msgtBeingMove,7*4,-1);
}

void msgNewGrenade(const vec pos, const vec rot, float pwr, int cluster, float clusterPwr){
	packet *p = &packetBuffer;



@@ 274,7 291,7 @@ void msgFxBeamBlaster(int c, const vec pa, const vec pb, float beamSize, float d
	packetQueueExcept(p,msgtFxBeamBlaster,8*4,c);
}

void msgItemDropUpdate(int c, const vec pos, const vec vel, const item *itm, u16 i, u16 len){
void msgItemDropUpdate(int c, const vec pos, const vec vel, const item *itm, u16 i, u16 len, i16 IDPlayer){
	packet *p = &packetBuffer;

	p->v.u16[0] = i;


@@ 291,7 308,10 @@ void msgItemDropUpdate(int c, const vec pos, const vec vel, const item *itm, u16
	p->v.f[6]   = vel.y;
	p->v.f[7]   = vel.z;

	packetQueue(p,msgtItemDropUpdate,8*4,c);
	p->v.i16[16] = IDPlayer;
	p->v.i16[17] = 0;

	packetQueue(p,msgtItemDropUpdate,9*4,c);
}

void msgBeingGotHit(i16 hp, u8 cause,float knockbackMult, being target, being culprit){


@@ 463,6 483,8 @@ const char *networkGetMessageName(uint i){
		return "setChungusLoaded";
	case msgtBeingGotHit:
		return "beingGotHit";
	case msgtBeingMove:
		return "beingMove";
	case msgtSetTime:
		return "setTime";
	case msgtItemDropNew:

M common/src/network/messages.h => common/src/network/messages.h +2 -1
@@ 17,6 17,7 @@ void msgBlockMiningUpdate        (int c, u16 x, u16 y, u16 z, i16 damage, u16 co
void msgSendChungusComplete      (int c,  u8 x,  u8 y,  u8 z);
void msgBeingGotHit              (       i16 hp, u8 cause, float knockbackMult, being target, being culprit);
void msgBeingDamage              (int c, i16 hp, u8 cause, float knockbackMult, being target, being culprit, const vec pos);
void msgBeingMove                (being b, vec dpos, vec dvel);
void msgSetTime                  (int c, u32 time);
// 9 = playerSendName
void msgItemDropNew              (int c, const vec pos, const vec vel, const item *itm);


@@ 35,7 36,7 @@ void msgGrenadeExplode           (const vec pos,float pwr, u16 style);
void msgGrenadeUpdate            (int c, const vec pos, const vec vel, u16 i, u16 count);
void msgFxBeamBlaster            (int c, const vec pa, const vec pb, float beamSize, float damageMultiplier);
void msgFxBeamBlastHit           (int c, const vec pos, u16 size, u16 style);
void msgItemDropUpdate           (int c, const vec pos, const vec vel, const item *itm, u16 i, u16 len);
void msgItemDropUpdate           (int c, const vec pos, const vec vel, const item *itm, u16 i, u16 len, i16 IDPlayer);
void msgPlayerSetData            (int c, i16 hp, u16 activeItem, u32 flags, u16 id);
void msgPlayerSetInventory       (int c, const item *itm, size_t itemCount);
void msgPingPong                 (int c);

M common/src/network/packet.h => common/src/network/packet.h +1 -0
@@ 69,6 69,7 @@ typedef enum {
	msgtBlockMiningUpdate,
	msgtSetChungusLoaded,
	msgtBeingGotHit,
	msgtBeingMove,
	msgtSetTime,
	msgtItemDropNew,
	msgtGrenadeNew,

M common/src/nuj/items.nuj => common/src/nuj/items.nuj +4 -4
@@ 325,10 325,10 @@
	[sync]
]]

[def i-assaultblaste]
[def i-assaultblaster]
[item-default [ω
	[def id [item-new-id]]
	[def sym 'i-assaultblaste]
	[def sym 'i-assaultblaster]
	[def name "Assault Blaster"]
	[def inaccuracy 8]
	[def ammunition 'i-flamebullet]


@@ 359,7 359,7 @@
	]]
	[def burn-up [λ [pos id amount] [explode pos [* amount 0.2]]]]
	[def sprite-id-0 263]
	[def mesh 'm-assaultblaste]
	[def mesh 'm-assaultblaster]
	[def weight 3.0]

	[sync]


@@ 383,7 383,7 @@
	[def tertiary [λ [] [item-reload 256]]]
	[def burn-up [λ [pos id amount] [explode pos [* amount 0.2]]]]
	[def sprite-id-0 264]
	[def mesh 'm-shotgunblaste]
	[def mesh 'm-shotgunblaster]
	[def weight 3.0]

	[sync]

M common/src/world/world.h => common/src/world/world.h +1 -0
@@ 14,6 14,7 @@ chunk   *worldGetChunk      (int x, int y, int z);
bool     worldIsLoaded      (int x, int y, int z);
ivec     chungusGetPos      (const chungus *c);
void     worldMine          (int x, int y, int z);
void     worldBreak         (int x, int y, int z);
void     worldBoxMine       (int x, int y, int z, int w,int h,int d);
void     worldBoxMineSphere (int x, int y, int z, int r);
bool     worldShouldBeLoaded(const vec cpos);

M server/src/game/blockMining.c => server/src/game/blockMining.c +18 -16
@@ 80,7 80,7 @@ void blockMiningDropItemsPos(int x, int y, int z, u8 b){
	float xoff = ((float)rngValM(1024) / 2048.f)+0.25f;
	float yoff = ((float)rngValM(1024) / 4096.f)+0.25f;
	float zoff = ((float)rngValM(1024) / 2048.f)+0.25f;
	itemDropNewP(vecNew(x + xoff,y + yoff,z + zoff), &i);
	itemDropNewP(vecNew(x + xoff,y + yoff,z + zoff), &i, -1);
}

void blockMiningMine(uint i, int dmg){


@@ 118,25 118,27 @@ int blockMiningMinePosItem(item *itm, int x, int y, int z){
	return blockMiningMinePos(dmg,x,y,z);
}

void blockMiningMineBlock(int x, int y, int z){
void blockMiningMineBlock(int x, int y, int z, u8 cause){
	const u8 b = worldGetB(x,y,z);
	if(b == 0){return;}
	msgMineBlock(x,y,z,b,0);
	if((b == I_Grass) || (b == I_Dry_Grass) || (b == I_Roots)){
		worldSetB(x,y,z,I_Dirt);
		switch(b){
		case I_Roots: {
			item itm = itemNew(I_Oak,1);
			itemDropNewP(vecNew(x,y,z),&itm);
			break; }
		case I_Grass: {
			item itm = itemNew(I_Plantmatter,1);
			itemDropNewP(vecNew(x,y,z),&itm);
			break; }
		case I_Dry_Grass: {
			item itm = itemNew(I_Straw,1);
			itemDropNewP(vecNew(x,y,z),&itm);
			break; }
		if(cause == 0){
			switch(b){
			case I_Roots: {
				item itm = itemNew(I_Oak,1);
				itemDropNewP(vecNew(x,y,z),&itm,-1);
				break; }
			case I_Grass: {
				item itm = itemNew(I_Plantmatter,1);
				itemDropNewP(vecNew(x,y,z),&itm,-1);
				break; }
			case I_Dry_Grass: {
				item itm = itemNew(I_Straw,1);
				itemDropNewP(vecNew(x,y,z),&itm,-1);
				break; }
			}
		}
	}else{
		worldSetB(x,y,z,0);


@@ 179,7 181,7 @@ void blockMiningUpdateAll(){
		}else{
			bm->wasMined = false;
			if(bm->damage > blockTypeGetHealth(bm->b)){
				blockMiningMineBlock(bm->x,bm->y,bm->z);
				blockMiningMineBlock(bm->x,bm->y,bm->z,0);
				blockMiningDel(i);
			}
		}

M server/src/game/blockMining.h => server/src/game/blockMining.h +1 -1
@@ 3,7 3,7 @@

void blockMiningBurnBlock    (int x, int y, int z, u8 b);
void blockMiningDropItemsPos (int x, int y, int z, u8 b);
void blockMiningMineBlock    (int x, int y, int z);
void blockMiningMineBlock    (int x, int y, int z, u8 cause);
int  blockMiningMinePos      (int dmg, int x, int y, int z);
int  blockMiningMinePosItem  (item *itm, int x, int y, int z);
void blockMiningUpdateAll    ();

M server/src/game/grenade.c => server/src/game/grenade.c +1 -1
@@ 51,7 51,7 @@ void grenadeNew(const vec pos, const vec rot, float pwr, int cluster, float clus
	int g       = grenadeCount++;
	float speed = 0.12f;

	grenadeList[g].ent = entityNew(pos,rot);
	grenadeList[g].ent = entityNew(pos,rot,pwr*3.f);
	if(pwr < 1.5f){
		speed = 0.15f;
	}

M server/src/game/itemDrop.c => server/src/game/itemDrop.c +8 -8
@@ 36,13 36,13 @@
void itemDropUpdateMsg(u8 c,uint i){
	if(i >= itemDropCount)         {return;}
	if(itemDropList[i].ent == NULL){return;}
	msgItemDropUpdate(c,itemDropList[i].ent->pos,itemDropList[i].ent->vel,&itemDropList[i].itm,i,itemDropCount);
	msgItemDropUpdate(c,itemDropList[i].ent->pos,itemDropList[i].ent->vel,&itemDropList[i].itm,i,itemDropCount,itemDropList[i].player);
}

uint itemDropUpdatePlayer(uint c, uint offset){
	const item iZero = {0,0};
	const uint max = MIN(offset+clients[c].itemDropUpdateWindowSize,itemDropCount);
	if(itemDropCount == 0){msgItemDropUpdate(c,vecZero(),vecZero(),&iZero,0,0);}
	if(itemDropCount == 0){msgItemDropUpdate(c,vecZero(),vecZero(),&iZero,0,0,-1);}
	for(uint i=0;i<clients[c].itemDropPriorityQueueLen;i++){
		itemDropUpdateMsg(c,clients[c].itemDropPriorityQueue[i]);
	}


@@ 77,14 77,14 @@ itemDrop *itemDropNew(){
	return &itemDropList[itemDropCount++];
}

void itemDropNewP(const vec pos,const item *itm){
void itemDropNewP(const vec pos,const item *itm, i16 IDPlayer){
	if(itm == NULL){return;}
	itemDrop *id = itemDropNew();
	if(id == NULL){return;}

	id->itm      = *itm;
	id->ent      = entityNew(pos,vecZero());
	id->player   = -1;
	id->ent      = entityNew(pos,vecZero(),itemGetWeight(&id->itm));
	id->player   = IDPlayer;
	id->lastFire =  0;
	id->fireDmg  =  0;
	entityUpdateCurChungus(id->ent);


@@ 95,10 95,10 @@ void itemDropNewPacket(uint c, const packet *p){
	itemDrop *id = itemDropNew();
	if(id == NULL){return;}

	id->ent        = entityNew(vecNewP(&p->v.f[0]),vecZero());
	id->ent->vel   = vecNewP(&p->v.f[3]);
	id->itm.ID     = p->v.u16[12];
	id->itm.amount = p->v.i16[13];
	id->ent        = entityNew(vecNewP(&p->v.f[0]),vecZero(),itemGetWeight(&id->itm));
	id->ent->vel   = vecNewP(&p->v.f[3]);
	id->player     = c;
	id->lastFire   = 0;
	id->fireDmg    = 0;


@@ 217,7 217,7 @@ void itemDropUpdateAll(){
		}
	}

	for(uint i=itemDropCount-(1+(calls&0x1F));i<itemDropCount;i-=0x20){
	for(uint i=itemDropCount-(1+(calls&0x3F));i<itemDropCount;i-=0x40){
		itemDropUpdateFire(i);
	}
	calls++;

M server/src/game/throwable.c => server/src/game/throwable.c +2 -1
@@ 19,10 19,11 @@

#include "../network/server.h"
#include "../../../common/src/game/entity.h"
#include "../../../common/src/game/item.h"

void throwableNew(const vec pos, const vec rot, float speed, const item itm, being thrower, i8 damage, u8 flags){
	throwable *a = throwableAlloc();
	a->ent       = entityNew(pos,rot);
	a->ent       = entityNew(pos,rot,itemGetWeight(&itm));
	a->ent->vel  = vecMulS(vecDegToVec(rot),speed);
	a->itm       = itm;
	a->damage    = damage;

M server/src/misc/client_stubs.c => server/src/misc/client_stubs.c +2 -3
@@ 18,6 18,7 @@
 * meant for the client side.
 */
#include "../../../common/src/common.h"
#include "../../../common/src/network/messages.h"
#include "../../../common/src/misc/side.h"

#include <stdio.h>


@@ 43,9 44,7 @@ void fxRainDrop(const vec pos){
}

void fxBlockBreak(const vec pos, u8 b, u8 cause){
	(void)pos;
	(void)b;
	(void)cause;
	msgMineBlock(pos.x,pos.y,pos.z,b,cause);
}

void ingredientSubstituteAdd(u16 ingredient, u16 substitute){

M server/src/misc/lisp.c => server/src/misc/lisp.c +10 -1
@@ 90,6 90,14 @@ static lVal *wwlnfIDCount(lClosure *c, lVal *v){
	(void)c;(void)v;
	return lValInt(itemDropGetActive());
}
static lVal *wwlnfIDFlush(lClosure *c, lVal *v){
	(void)c;(void)v;
	for(int i=itemDropCount-1;i>=0;i--){
		itemDropDel(i);
		addPriorityItemDrop(i);
	}
	return NULL;
}
static lVal *wwlnfECount(lClosure *c, lVal *v){
	(void)c;(void)v;
	return lValInt(entityCount);


@@ 478,7 486,7 @@ static lVal *wwlnfItemDropNew(lClosure *c, lVal *v){

	if((pos.x < 0) || (id < 0) || (amount < 0)){return NULL;}
	item itm = itemNew(id,amount);
	itemDropNewP(pos,&itm);
	itemDropNewP(pos,&itm,-1);
	return NULL;
}



@@ 488,6 496,7 @@ void addServerNativeFuncs(lClosure *c){
	lAddNativeFunc(c,"fire-count",     "()",                                           "Returns fire count",                                         wwlnfFCount);
	lAddNativeFunc(c,"mining-count",   "()",                                           "Returns block mining count",                                 wwlnfBMCount);
	lAddNativeFunc(c,"item-drop-count","()",                                           "Returns item drop count",                                    wwlnfIDCount);
	lAddNativeFunc(c,"item-drop-flush!","()",                                          "Remove all itemDrops",                                       wwlnfIDFlush);
	lAddNativeFunc(c,"entity-count",   "()",                                           "Returns entity count",                                       wwlnfECount);
	lAddNativeFunc(c,"chungus-count",  "()",                                           "Returns chungus count",                                      wwlnfChungi);
	lAddNativeFunc(c,"rain-count",     "()",                                           "Returns amount of rain drops",                               wwlnfRCount);

M server/src/network/server.c => server/src/network/server.c +13 -1
@@ 315,6 315,15 @@ void packetEchoExcept(u8 c,const packet *p){
	sendToAllExcept(c,p,packetLen(p)+4);
}

void beingMove(u8 c, const packet *p){
	(void)c;
	being b = p->v.u32[0];
	vec dpos = vecNewP(&p->v.f[1]);
	vec dvel = vecNewP(&p->v.f[4]);
	beingAddPos(b,dpos);
	beingAddVel(b,dvel);
}

void serverParseSinglePacket(uint c, packet *p){
	const int pLen  = p->typesize >> 10;
	const int pType = p->typesize & 0xFF;


@@ 338,7 347,7 @@ void serverParseSinglePacket(uint c, packet *p){
		worldSetB(p->v.u16[0],p->v.u16[1],p->v.u16[2],p->v.u16[3]);
		break;
	case msgtMineBlock:
		blockMiningMineBlock(p->v.u16[0],p->v.u16[1],p->v.u16[2]);
		blockMiningMineBlock(p->v.u16[0],p->v.u16[1],p->v.u16[2],p->v.u8[7]);
		break;
	case msgtGoodbye:
		errno=0;


@@ 415,6 424,9 @@ void serverParseSinglePacket(uint c, packet *p){
	case msgtThrowableRecvUpdates:
		throwableRecvUpdate(p);
		break;
	case msgtBeingMove:
		beingMove(c,p);
		break;

	case msgtLZ4:
	case msgtPlayerPos:

M server/src/nujel/server.nuj => server/src/nujel/server.nuj +7 -7
@@ 122,21 122,21 @@

	[set-inv! 0 i-blaster]
	[set-inv! 1 i-masterblaster]
	[set-inv! 2 i-assaultblaste]
	[set-inv! 2 i-assaultblaster]
	[set-inv! 3 i-shotgun]
	[set-inv! 4 i-crystalaxe]
	; [set-inv! 5 i-flintandsteel]
	[set-inv! 5 i-flamestick]
	[set-inv! 5 i-crystalpickaxe]
	;[set-inv! 5 i-flamestick]
	[set-inv! 6 i-crystalspear]
	[set-inv! 7 i-pear 42]
	[set-inv! 8 i-dirt 99]
	[set-inv! 9 i-grenade 99]

	[set-inv! 10 i-crystalbulle 999]
	[set-inv! 11 i-crystalbulle 999]
	[set-inv! 12 i-crystalbulle 999]
	[set-inv! 10 i-crystalbullet 999]
	[set-inv! 11 i-crystalbullet 999]
	[set-inv! 12 i-crystalbullet 999]
	[set-inv! 13 i-flamebullet 999]
	[set-inv! 14 i-flamebullet 999]
	[set-inv! 15 i-flamebullet 999]
	[set-inv! 16 i-crystalpickax]
	[set-inv! 16 i-flintandsteel]
]]

M server/src/persistence/itemDrop.c => server/src/persistence/itemDrop.c +1 -1
@@ 56,7 56,7 @@ const void *itemDropLoad(const void *buf){
	id->itm.ID     = s[1];
	id->itm.amount = s[2];

	id->ent = entityNew(vecNewP(&f[2]),vecZero());
	id->ent = entityNew(vecNewP(&f[2]),vecZero(), itemGetWeight(&id->itm));
	if(id->ent == NULL){return b+32;}
	id->ent->vel = vecNewP(&f[5]);


M server/src/persistence/throwable.c => server/src/persistence/throwable.c +1 -1
@@ 68,7 68,7 @@ const void *throwableLoad(const void *buf){
	t->itm.amount = s[3];
	t->counter    = s[4];

	t->ent = entityNew(vecNewP(&f[3]),vecNew(f[9],f[10],0));
	t->ent = entityNew(vecNewP(&f[3]),vecNew(f[9],f[10],0),itemGetWeight(&t->itm));
	if(t->ent == NULL){return b+44;}
	t->ent->vel = vecNewP(&f[6]);


M server/src/voxel/bigchungus.c => server/src/voxel/bigchungus.c +10 -4
@@ 178,10 178,13 @@ void bigchungusBoxSphere(bigchungus *c, int x,int y,int z, int r, u8 block){
}

void bigchungusMine(bigchungus *c, int x,int y,int z){
	u8 b = bigchungusGetB(c,x,y,z);
	if(b==0){return;}
	bigchungusSetB(c,x,y,z,0);
	blockMiningDropItemsPos(x,y,z,b);
	(void)c;
	blockMiningMineBlock(x,y,z,0);
}

void bigchungusBreak(bigchungus *c, int x,int y,int z){
	(void)c;
	blockMiningMineBlock(x,y,z,1);
}

void bigchungusBoxMine(bigchungus *c, int x,int y,int z, int w,int h,int d){


@@ 380,6 383,9 @@ int checkCollision(int x, int y, int z){
void worldMine(int x, int y, int z){
	bigchungusMine(&world,x,y,z);
}
void worldBreak(int x, int y, int z){
	bigchungusBreak(&world,x,y,z);
}
void worldBoxMine(int x, int y, int z, int w,int h,int d){
	bigchungusBoxMine(&world,x,y,z,w,h,d);
}

M server/src/voxel/bigchungus.h => server/src/voxel/bigchungus.h +1 -0
@@ 51,6 51,7 @@ bool     worldSetB          (int x, int y, int z, u8 block);
int      checkCollision     (int x, int y, int z);
void     worldDirtyChunk    (int x, int y, int z, int client);
void     worldMine          (int x, int y, int z);
void     worldBreak         (int x, int y, int z);
void     worldBoxMine       (int x, int y, int z, int w,int h,int d);
void     worldBoxMineSphere (int x, int y, int z, int r);
bool     worldIsLoaded      (int x, int y, int z);