-----------------------------------------------------------------------
--                          CAMPING MOD                              --
--                      CODE BY ROBERT JOHNSON                       --
--						  TEXTURE BY THUZTOR                         --
-----------------------------------------------------------------------
--                          OFFICIAL TOPIC                           --
--   http://theindiestone.com/community/viewtopic.php?f=31&t=8968    --
--                                                                   --
-----------------------------------------------------------------------

require 'luautils'

camping = {};
gameTime = {};
camping.playerData = nil
camping.campfires = {};
camping.hourElapsed = 0;
camping.previousHour = 0;
camping.campfireXp = 0;
camping.tentSprites = {
	sheet = {
		frontLeft = "TileIndieStoneTentFrontLeft",
		backLeft = "TileIndieStoneTentBackLeft",
		frontRight = "TileIndieStoneTentFrontRight",
		backRight = "TileIndieStoneTentBackRight"
	},
	tarp = {
		frontLeft = "camping_01_3",
		backLeft = "camping_01_2",
		frontRight = "camping_01_0",
		backRight = "camping_01_1"
	},
}

camping.lightFireWithSteelAndFlint = function()
	-- fireSteelAndFlintAction
end

function fireSteelAndFlintAction()
	local currentCampfire = camping.getCurrentCampfire();
	-- 1 to 3 chance to start fire with wood kit !
	local randFireNumber = 3 - camping.campfireXp;
	if(randFireNumber < 1) then
		randFireNumber = 1;
	end
	local randFire = ZombRand(randFireNumber);
	if(randFire == 0) then
		currentCampfire.fireLvl = 2;
		camping.changeFireLvl(currentCampfire);
		camping.gainXp();
	end
end

camping.lightFireWithWoodKit = function()
	--fireWoodAction
end

-- light the campfire with wood (Kindling)
function fireWoodAction(currentCampfire, player, isOutdoorsMan)
	-- 1 to 5 chance to start fire with wood kit !
	-- a outdoorsman have a greater chance to light the fire
	local randNumber = 6;
	if isOutdoorsMan then
		randNumber = 2;
	end
	if ZombRand(randNumber) == 0 then
		currentCampfire.fuelAmt = 6 * 60
		camping.changeFireLvl(currentCampfire);
	else
		-- fail ? Maybe the wood kit will broke...
		if ZombRand(randNumber) == 0 then
			player:Say("I broke my kindling...");
			player:getInventory():Remove("FireWoodKit");
		else
			player:Say("Crap, I fail...");
		end
	end
end

-- The Doors FTW ! :)
camping.lightMyFire = function(campfire, player, lighter, petrol)
	if campfire.isLit or campfire.fuelAmt <= 0 then return end
	lighter:Use()
	petrol:Use()
	if isClient() then
		local cf = campfire
		local args = { x = cf.x, y = cf.y, z = cf.z }
		sendClientCommand(player, 'camping', 'lightFire', args)
	else
		camping.lightFire(campfire)
	end
end

function camping.lightFire(campfire)
	if campfire.isLit or campfire.fuelAmt <= 0 then return end
	campfire.isLit = true
	camping.changeFireLvl(campfire)
end

function camping.putOutCampfire(campfire)
	if not campfire.isLit then return end
	campfire.isLit = false
	campfire.fuelAmt = campfire.fuelAmt * 0.90
	camping.changeFireLvl(campfire)
end

camping.syncFireObject = function(campfire)
	campfire.transmitObject = false
	if not campfire:getObject() then
		campfire:addObject()
		campfire.transmitObject = true
	end
end

camping.syncFireSprite = function(campfire)
	campfire.transmitSprite = false
	local spriteName
	if not campfire.isLit then
		spriteName = "camping_01_6"
--	elseif campfire.fuelAmt <= 3 * 60 then
--		spriteName = "camping_01_4"
	else
		spriteName = "camping_01_5"
	end
	if spriteName ~= campfire.spriteName then
		campfire:setSpriteName(spriteName)
		campfire.transmitSprite = true
	end
end

camping.syncFireModData = function(campfire)
	local object = campfire:getObject()
	if object then
		campfire:toModData(object:getModData())
	end
end

camping.syncFireContainer = function(campfire)
	local container = campfire:getContainer()
	if not container then
		campfire:addContainer()
		campfire.transmitObject = true
	end
	local t
	if not campfire.isLit then
		t = 0
	elseif campfire.fuelAmt <= 3 * 60 then
		t = 1.7
	else
		t = 1.9
	end
	campfire.transmitContainerTemp = false
	if math.abs(t - container:getCustomTemperature()) > 0.01 then
		camping.noise('container temp changed from '..container:getCustomTemperature()..' to '..t)
		container:setCustomTemperature(t)
		campfire.transmitContainerTemp = isServer()
	end
end

camping.syncFireFire = function(campfire)
	campfire.transmitFire = false
	local fireObj = campfire:getFireObject()
	if campfire.isLit then
		if not fireObj then
			campfire:addFireObject()
			campfire.transmitFire = true
		end
	elseif fireObj then
		campfire:removeFireObject()
	end
end

camping.changeFireLvl = function(campFire)
	if campFire.fuelAmt <= 0 then
		campFire.isLit = false
	end

	local object = campFire:getObject()
	if not object then
		camping.saveData(campFire)
		return
	end

	local radius = camping.fireRadius(campFire)
	if campFire.radius == radius then
		camping.saveData(campFire)
		object:transmitModData()
		return
	end
	campFire.radius = radius

	local gs = campFire:getSquare()
	camping.noise('changeFireLvl x,y,z='..gs:getX()..','..gs:getY()..','..gs:getZ()..' fuelAmt='..campFire.fuelAmt..' isLit='..tostring(campFire.isLit)..' radius='..radius)

	camping.syncFireObject(campFire)
	camping.syncFireSprite(campFire)
	camping.syncFireModData(campFire)
	camping.syncFireContainer(campFire)

	local object = campFire:getObject()
	if campFire.transmitObject then
		camping.noise('transmit campfire object')
		object:transmitCompleteItemToClients()
	else
		if campFire.transmitSprite then
			camping.noise('transmit campfire sprite')
			object:transmitUpdatedSpriteToClients()
		end
		camping.noise('transmit campfire modData')
		object:transmitModData()
		if campFire.transmitContainerTemp then
			camping.noise('transmit campfire container temperature')
			object:sendObjectChange('container.customTemperature')
		end
	end
	
	camping.syncFireFire(campFire)

	local fireObj = campFire:getFireObject()
	if fireObj and campFire.transmitFire then
		fireObj:transmitCompleteItemToClients()
	end

	if fireObj and fireObj:getLightRadius() ~= campFire.radius then
		fireObj:setLightRadius(campFire.radius)
		if isServer() then
			camping.noise('transmit campfire light radius')
			fireObj:sendObjectChange('lightRadius')
		end
	end

	camping.saveData(campFire)
end

camping.fireRatio = function(campFire)
	if not campFire.isLit then return 0 end
	local maxFuel = 6 * 60
	return math.min(campFire.fuelAmt, maxFuel) / maxFuel
end

camping.fireRadius = function(campFire)
	if not campFire.isLit then return 0 end
	local minRadius = 2
	local maxRadius = 18
	local maxFuel = 6 * 60
	return math.max(minRadius, maxRadius * math.min(campFire.fuelAmt, maxFuel) / maxFuel)
end

camping.addFuel = function(campfire, fuelAmt)
	campfire.fuelAmt = campfire.fuelAmt + fuelAmt
	camping.changeFireLvl(campfire)
end

-- add a campfire to the ground
camping.addCampfire = function(grid)
	if not grid then return end
	if camping.findCampfireObject(grid) then return end

	local newCampFire = ISCampfire:new(grid:getX(), grid:getY(), grid:getZ())
	newCampFire:addObject()
	newCampFire:addContainer()
	table.insert(camping.campfires, newCampFire)
	newCampFire:getObject():transmitCompleteItemToClients()

	local modData = {}
	newCampFire:toModData(modData)
	modData.x = newCampFire.x
	modData.y = newCampFire.y
	modData.z = newCampFire.z
	table.insert(camping.playerData.camping.campfires, modData)

	camping.noise("#camping.campfires="..#camping.campfires)
	camping.noise("#camping.playerData.camping.campfires="..#camping.playerData.camping.campfires)

	camping.saveData(newCampFire)
	return newCampFire;
end

function camping.findTentSprites(sprite)
	for _,sprites in pairs(camping.tentSprites) do
		if sprite == sprites.frontLeft or sprite == sprites.backLeft or
				sprite == sprites.frontRight or sprite == sprites.backRight then
			return sprites
		end
	end
	return nil
end

-- add a tent to the ground
function camping.addTent(grid, sprite)
	if not grid then return end
	if camping.findTentObject(grid) then return end

	local tentSprites = camping.findTentSprites(sprite)
	if not tentSprites then return end

	local tent = IsoObject.new(grid, sprite, "Tent")
	grid:AddTileObject(tent)
	tent:transmitCompleteItemToClients()

	local dx = 0
	local dy = 0
	if sprite == tentSprites.frontLeft then
		sprite = tentSprites.backLeft
		dx = -1
	elseif sprite == tentSprites.frontRight then
		sprite = tentSprites.backRight
		dy = -1
	else
		error "expected front tent sprite"
	end

	grid = getCell():getGridSquare(grid:getX() + dx, grid:getY() + dy, grid:getZ())
	tent = IsoObject.new(grid, sprite, "Tent")
	grid:AddTileObject(tent)
	tent:transmitCompleteItemToClients()

	return tent;
end

function camping.isValidModData(modData)
	if modData.fuelAmt then return true end
	return false
end

camping.removeModData = function(prefix)
	local keys = {}
	for k,_ in pairs(camping.playerData) do
		if luautils.stringStarts(k, prefix) then
			camping.noise('removing "'..k..'" from modData')
			table.insert(keys, k)
		end
	end
	for _,k in pairs(keys) do
		camping.playerData[k] = nil
	end
end

-- remove a tent
function camping.removeTent(tent)
	if not tent then return end
	local grid = tent:getSquare()
	if not grid then return end

	local tentSprites = camping.findTentSprites(tent:getSpriteName())
	if not tentSprites then return end

	grid:transmitRemoveItemFromSquare(tent)

	local dx = 0
	local dy = 0
	if tent:getSpriteName() == tentSprites.frontLeft then
		dx = -1
	elseif tent:getSpriteName() == tentSprites.backLeft then
		dx = 1
	elseif tent:getSpriteName() == tentSprites.frontRight then
		dy = -1
	elseif tent:getSpriteName() == tentSprites.backRight then
		dy = 1
	end

	grid = getCell():getGridSquare(grid:getX() + dx, grid:getY() + dy, grid:getZ())
	tent = camping.findTentObject(grid)
	if not tent then return end
	grid:transmitRemoveItemFromSquare(tent)
end

-- remove a camp fire
camping.removeCampfire = function(campfire)
	if not campfire then return end

	campfire:transferItemsToGround()
	campfire:removeFireObject()
	campfire:removeObject()

	for i=1,#camping.campfires do
		if camping.campfires[i] == campfire then
			table.remove(camping.campfires, i)
			break
		end
	end
	for i=1,#camping.playerData.camping.campfires do
		local data = camping.playerData.camping.campfires[i]
		if data.x == campfire.x and data.y == campfire.y and data.z == campfire.z then
			table.remove(camping.playerData.camping.campfires, i)
			break
		end
	end
	camping.noise("#camping.campfires="..#camping.campfires)
	camping.noise("#camping.playerData.camping.campfires="..#camping.playerData.camping.campfires)

	-- we give back the campfire kit to the player
--	camping.player:getInventory():AddItem("camping.CampfireKit");

	-- refresh the loot containers
--	for i=0, getNumActivePlayers() -1 do
--		local pdata = getPlayerData(i)
--		if pdata and pdata.lootInventory then
--			pdata.lootInventory:refreshBackpacks()
--		end
--	end
end

function camping.isCampfireObject(object)
	if not object then return false end
	return object:getObjectName() == "Campfire"
end

function camping.findCampfireObject(square)
	if not square then return nil end
	for i=0,square:getObjects():size()-1 do
		local object = square:getObjects():get(i)
		if camping.isCampfireObject(object) then
			return object
		end
	end
	return nil
end

function camping.getCampfireAt(x, y, z)
	if isClient() then return nil end
	for _,vCur in pairs(camping.campfires) do
		if vCur.x == x and vCur.y == y and vCur.z == z then
			return vCur
		end
	end
	return nil
end

function camping.getCampfireOnSquare(square)
	if square == nil then
		square = getPlayer():getCurrentSquare()
	end
	return camping.getCampfireAt(square:getX(), square:getY(), square:getZ())
end

-- return the campfire on the gridSquare the player is standing on
-- or from the gridsquare in parameter (if from context menu for example)
camping.getCurrentCampfire = function(square)
	if not square then return nil end
	-- Client doesn't have a list of campfires
	if isClient() then
		local object = camping.findCampfireObject(square)
		if object then
			local md = object:getModData()
			if md and camping.isValidModData(md) then
				local campfire = ISCampfire:new(square:getX(), square:getY(), square:getZ())
				campfire:fromModData(object:getModData())
				return campfire
			end
		end
		return nil
	end
	return camping.getCampfireOnSquare(square)
end

-- bit of ugliness, see camping.getCurrentCampfire
function camping.updateClientCampfire(campfire)
	if not campfire or not isClient() then return end
	local object = campfire:getObject()
	if object then
		campfire:fromModData(object:getModData())
	end
end

function camping.isTentObject(object)
	if not object then return false end
	return object:getObjectName() == "Tent"
end

function camping.findTentObject(square)
	if not square then return nil end
	for i=0,square:getObjects():size()-1 do
		local object = square:getObjects():get(i)
		if camping.isTentObject(object) then
			return object
		end
	end
	return nil
end

function camping.tentAt(x, y, z)
	return camping.findTentObject(getCell():getGridSquare(x, y, z))
end

-- return the tent on the gridSquare the player is standing on
-- or from the gridsquare in parameter (if from context menu for example)
camping.getCurrentTent = function(grid)
	if not grid then return nil end
	return camping.findTentObject(grid)
end

-- remove the campfire or tent (sprite) from the grid
camping.removeTileFromGrid = function(grid)
	for _,v in pairs(grid:getLuaTileObjectList()) do
		if luautils.stringStarts(v:getObjectName(), "Campfire") then
			grid:transmitRemoveItemFromSquare(v)
		elseif luautils.stringStarts(v:getObjectName(), "Tent") then
			grid:transmitRemoveItemFromSquare(v)
		end
	end
end

camping.saveData = function(campfire, tent)
	if campfire then
		camping.noise('update GameTime modData for campfire '..campfire.x..','..campfire.y..','..campfire.z)
		local object = campfire:getObject()
		if object then
			campfire:toModData(object:getModData())
		end
		for i=1,#camping.playerData.camping.campfires do
			local data = camping.playerData.camping.campfires[i]
			if data.x == campfire.x and data.y == campfire.y and data.z == campfire.z then
				campfire:toModData(data)
				break
			end
		end
	end
end

function camping.convertOldModData()
	camping.removeModData("tent:")
	if camping.playerData.camping and camping.playerData.camping.campfires then return end
	camping.playerData.camping = {}
	camping.playerData.camping.campfires = {}
	camping.noise('converting old-style GameTime modData')
	local indexes = {}
	for iPData,vPData in pairs(camping.playerData) do
		camping.noise(tostring(iPData)..'='..tostring(vPData))
		for index in string.gmatch(iPData, "^campfire:(.+):") do
			if tonumber(index) then
				if indexes[tonumber(index)] == nil then
					indexes[tonumber(index)] = index;
				end
			end
		end
	end
	local campfires = camping.playerData.camping.campfires
	for ind,var in pairs(indexes) do
		local x = camping.playerData["campfire:"..ind..":x"] or -1
		if x and x > -1 then
			local y = camping.playerData["campfire:" .. ind .. ":y"];
			local z = camping.playerData["campfire:" .. ind .. ":z"];
			local fireLvl = camping.playerData["campfire:" .. ind .. ":fireLvl"] or 0 -- compatibility
			local fuelAmt = camping.playerData["campfire:" .. ind .. ":fuelAmt"] or (fireLvl * 60)
			local exterior = camping.playerData["campfire:" .. ind .. ":exterior"]
			local campfire = {}
			campfire.x = x
			campfire.y = y
			campfire.z = z
			campfire.exterior = exterior == true or exterior == nil
			campfire.fuelAmt = fuelAmt
			campfire.isLit = fuelAmt > 0
			table.insert(campfires, campfire)
		end
		camping.removeModData("campfire:" .. ind .. ":")
	end
	camping.noise('converted '..#campfires..' campfires')
end

-- load all our tent and campfire
camping.loadDatas = function()
	if isClient() then return end
	camping.noise('loading GameTime modData')
	gameTime = GameTime:getInstance();
	camping.playerData = gameTime:getModData();
	local sec = math.floor(gameTime:getTimeOfDay() * 3600);
	camping.previousHour = math.floor(sec / 3600);
	-- FIXME: if campfireXp is used, need to put it into player's modData
	camping.campfireXp = camping.playerData["campfireXp"] or 0;

	if camping.playerData.camping and #camping.playerData.camping.campfires == 0 then
		-- FIXME: this gets called twice, once before GameTime has been loaded
		camping.playerData.camping.campfires = nil
	end
	camping.convertOldModData()

	camping.campfires = {}
	for i=1,#camping.playerData.camping.campfires do
		local data = camping.playerData.camping.campfires[i]
		local campfire = ISCampfire:new(data.x, data.y, data.z)
		campfire:fromModData(data)
		table.insert(camping.campfires, campfire)
		camping.noise('added campfire fuelAmt='..campfire.fuelAmt..' '..campfire.x..','..campfire.y..','..campfire.z)
	end
end

-- we lower by 1 the firelvl (every 3 hours if no more wood)
camping.lowerFirelvl = function()
	for _,vCamp in pairs(camping.campfires) do
		local square = vCamp:getSquare()
		if square then
			vCamp.exterior = square:isOutside()
            if not vCamp.exterior and ZombRand(5) == 0 and vCamp.isLit then
                local newSquare = getCell():getGridSquare(vCamp.x + 1, vCamp.y, vCamp.z);
                if newSquare then
                    IsoFireManager.StartFire(getCell(), newSquare, true, 100, 500);
                end
            end
		end
		if vCamp.isLit then
			local amt = 10
			if RainManager.isRaining() and vCamp.exterior then amt = 20 end
			vCamp.fuelAmt = math.max(vCamp.fuelAmt - amt, 0)
			camping.changeFireLvl(vCamp);
		end
	end
end

-- every ten minutes we gonna check things
camping.checkCamping = function()
	if isClient() then return end
	-- Subtract 10 minutes of fuel from every fire
	camping.lowerFirelvl()
end

-- attract the zombie to the campfire and warm the player
camping.nearCamp = function(delay)
	if isClient() then return end
	for _,vCamp in pairs(camping.campfires) do
		local gridSquare = vCamp:getSquare()
		-- if campfire is burning (and still there, I mean not destroy because of streaming)
		if vCamp.isLit and gridSquare then
			-- zombie are attracted 10 from the 10 next tile if fireLvl is at 1, or 20 if it's at 2
--~ 			local squareAround = luautils.getNextTiles(getWorld():getCell(), vCamp.gridSquare, vCamp.fireLvl * 10);
			local noiseRadius = camping.fireRadius(vCamp)
			addSound(getPlayer(), gridSquare:getX(),gridSquare:getY(),gridSquare:getZ(), noiseRadius, noiseRadius);
--~ 			for u,j in pairs(squareAround) do
--~ 				for k,l in pairs(j:getLuaMovingObjectList()) do
--~ 					if luautils.stringStarts(l:toString(), "zombie.characters.IsoZombie") then
--~ 						l:PathTo(vCamp.gridSquare:getX(), vCamp.gridSquare:getY(), vCamp.gridSquare:getZ(), false, delay);
--~ 					end
--~ 				end
--~ 			end
		end
	end
end

camping.reuseGridsquare = function(sq)
end

camping.loadGridsquare = function(sq)
	if isClient() then return end
	if not camping.playerData or not camping.playerData.camping then return end -- handle server soft reset
	local object = camping.findCampfireObject(sq)
	if object then
		local md = object:getModData()
		if md['campfire:fuelAmt'] then
			md.fuelAmt = tonumber(md['campfire:fuelAmt']) or 0 -- convert old-style data
			md['campfire:fuelAmt'] = nil
		end
		md['hasPetrol'] = nil
	end
	for _,campfire in pairs(camping.campfires) do
		if campfire.x == sq:getX() and campfire.y == sq:getY() and campfire.z == sq:getZ() then
			camping.noise("FOUND A CAMPFIRE LOADED : " .. campfire.x .. " " .. campfire.y);
			campfire.exterior = sq:isOutside()
			if object then
				camping.noise('reusing existing campfire object index='..object:getObjectIndex()..' sprite='..tostring(object:getSpriteName()))
				campfire.spriteName = object:getSpriteName() or "camping_01_6"
				campfire.radius = -1
				camping.changeFireLvl(campfire)
				camping.saveData(campfire, nil)
			else
				camping.noise('removing campfire-without-object '..sq:getX()..','..sq:getY()..','..sq:getZ())
				camping.removeCampfire(campfire)
			end
			return
		end
	end
	if object then
		camping.noise('found an unknown campfire object '..sq:getX()..','..sq:getY()..','..sq:getZ())
		local md = object:getModData()
		if camping.isValidModData(md) then
			local campfire = ISCampfire:new(sq:getX(), sq:getY(), sq:getZ())
			campfire:fromModData(md)
			table.insert(camping.campfires, campfire)

			md = {}
			campfire:toModData(md)
			md.x = campfire.x
			md.y = campfire.y
			md.z = campfire.z
			table.insert(camping.playerData.camping.campfires, md)
			camping.noise('added previously-unknown campfire '..sq:getX()..','..sq:getY()..','..sq:getZ())
		else
			camping.noise("couldn't find valid modData for the unknown campfire, removing it")
			sq:RemoveTileObject(object)
		end
	end
end

function camping.processContainerItems(object)
	if not object then return end
	local container = object:getContainer()
	if not container then return end
	local ProcessItems = getCell():getProcessItems()
	for i=1,container:getItems():size() do
		local item = container:getItems():get(i-1)
		if not ProcessItems:contains(item) then
			ProcessItems:add(item)
		end
	end
end

function camping.loadGridsquareJavaHook(sq, campfire, object)
	if isClient() then return end
	if not camping.playerData or not camping.playerData.camping then return end -- handle server soft reset
	if object then
		local md = object:getModData()
		if md['campfire:fuelAmt'] then
			md.fuelAmt = tonumber(md['campfire:fuelAmt']) or 0 -- convert old-style data
			md['campfire:fuelAmt'] = nil
		end
		md['hasPetrol'] = nil
		camping.processContainerItems(object)
	end
	if campfire then
		camping.noise("FOUND A CAMPFIRE LOADED : " .. campfire.x .. " " .. campfire.y);
		campfire.exterior = sq:isOutside()
		if object then
			camping.noise('reusing existing campfire object index='..object:getObjectIndex()..' sprite='..tostring(object:getSpriteName()))
			campfire.spriteName = object:getSpriteName() or "camping_01_6"
			campfire.radius = -1
			camping.changeFireLvl(campfire)
			camping.saveData(campfire, nil)
		else
			camping.noise('removing campfire-without-object '..sq:getX()..','..sq:getY()..','..sq:getZ())
			camping.removeCampfire(campfire)
		end
		return
	end
	if object then
		camping.noise('found an unknown campfire object '..sq:getX()..','..sq:getY()..','..sq:getZ())
		local md = object:getModData()
		if camping.isValidModData(md) then
			local campfire = ISCampfire:new(sq:getX(), sq:getY(), sq:getZ())
			campfire:fromModData(md)
			table.insert(camping.campfires, campfire)

			md = {}
			campfire:toModData(md)
			md.x = campfire.x
			md.y = campfire.y
			md.z = campfire.z
			table.insert(camping.playerData.camping.campfires, md)
			camping.noise('added previously-unknown campfire '..sq:getX()..','..sq:getY()..','..sq:getZ())
		else
			camping.noise("couldn't find valid modData for the unknown campfire, removing it")
			sq:RemoveTileObject(object)
		end
	end
end

camping.campfireAt = function(x, y, z)
	for _,v in pairs(camping.campfires) do
		if v.x == x and v.y == y and v.z == z then
			return v
		end
	end
	return nil
end

camping.OnClientCommand = function(module, command, player, args)
	if not isServer() then return end
	if module ~= 'camping' then return end
	local argStr = ''
	for k,v in pairs(args) do argStr = argStr..' '..k..'='..v end
	camping.noise('camping.OnClientCommand '..module..' '..command..' '..argStr)
	
	if command == 'addCampfire' then
		local gs = getCell():getGridSquare(args.x, args.y, args.z)
		if gs then
			camping.addCampfire(gs)
		end
	elseif command == 'addFuel' then
		local campfire = camping.campfireAt(args.x, args.y, args.z)
		if campfire then
			camping.addFuel(campfire, args.fuelAmt)
		end
	elseif command == 'lightFire' then
		local campfire = camping.campfireAt(args.x, args.y, args.z)
		if campfire then
			if args.fuelAmt then
				camping.addFuel(campfire, args.fuelAmt)
			end
			camping.lightFire(campfire)
		end
	elseif command == 'putOutCampfire' then
		local campfire = camping.campfireAt(args.x, args.y, args.z)
		if campfire then
			camping.putOutCampfire(campfire)
		end
	elseif command == 'removeCampfire' then
		local campfire = camping.campfireAt(args.x, args.y, args.z)
		if campfire then
			camping.removeCampfire(campfire)
			local kit = InventoryItemFactory.CreateItem("camping.CampfireKit")
			player:sendObjectChange('addItem', { item = kit } )
		end
	elseif command == 'addTent' then
		local gs = getCell():getGridSquare(args.x, args.y, args.z)
		if gs then
			camping.addTent(gs, args.sprite)
		end
	elseif command == 'removeTent' then
		local tent = camping.tentAt(args.x, args.y, args.z)
		if tent then
			camping.removeTent(tent)
			local kit = InventoryItemFactory.CreateItem("camping.CampingTentKit")
			player:sendObjectChange('addItem', { item = kit } )
		end
	end
end

-- OnGameBoot is to handle soft-reset, no effect on client/sp
camping.OnGameBoot = function()
	-- this is called before map_t.bin is loaded (if that file even exists)
	camping.playerData = getGameTime():getModData()
	camping.playerData.camping = {}
	camping.playerData.camping.campfires = {}
end

camping.attractZed = function()
	camping.nearCamp(0);
end

camping.wantNoise = getDebug()
camping.noise = function(msg)
	if (camping.wantNoise) then print('camping: '..msg) end
end

Events.EveryTenMinutes.Add(camping.attractZed);

Events.EveryTenMinutes.Add(camping.checkCamping);

--Events.OnGameStart.Add(camping.loadDatas);

Events.OnGameBoot.Add(camping.OnGameBoot)
Events.OnGameTimeLoaded.Add(camping.loadDatas)
if isServer() then
	Events.OnClientCommand.Add(camping.OnClientCommand)
end

--Events.ReuseGridsquare.Add(camping.reuseGridsquare);

--Events.LoadGridsquare.Add(camping.loadGridsquare);
