local assets=
{
    Asset("ANIM", "anim/miningmachine.zip"),
	
	Asset("ANIM", "anim/ui_mms.zip"),
	
	Asset("ANIM", "anim/swap_miningfuelmeter.zip"),
	
	Asset("ATLAS", "images/inventory/miningmachinekit_item.xml"),
    Asset("IMAGE", "images/inventory/miningmachinekit_item.tex"),

}

prefabs = {
}

require "prefabutil"

-----------------------------------------------------------STORAGE WIDGET SETUP-----------------------------------------------------

local containers = require "containers"
local prev_widgetsetup=containers.widgetsetup

local xmin, xmax, ymin, ymax

if TUNING.MMSTORAGESIZE == "ui_mms_2x2" then
	xmin = 0.5
	xmax = 1.5
	ymin = 0.5
	ymax = 1.5
elseif TUNING.MMSTORAGESIZE == "ui_mms_2x3" then
	xmin = 0.5
	xmax = 1.5
	ymin = 0
	ymax = 2
elseif TUNING.MMSTORAGESIZE == "ui_mms_4x3" then
	xmin = -0.5
	xmax = 2.5
	ymin = 0
	ymax = 2
elseif TUNING.MMSTORAGESIZE == "ui_mms_4x4" then
	xmin = -0.5
	xmax = 2.5
	ymin = -0.5
	ymax = 2.5
else -- if the config is overriden to an invalid value through modoverride.lua, at least it will load the 3x3 config and won't crash
	xmin = 0
	xmax = 2
	ymin = 0
	ymax = 2
end

local MMSwidgetparams =
	{
		widget =
		{
			slotpos = {},
			animbank = TUNING.MMSTORAGESIZE,
			animbuild = "ui_mms",
			pos = Vector3(0, 0, 0),
		},
		issidewidget = false,
		type = "chest",
	}
	
for y = ymax, ymin, -1 do
    for x = xmin, xmax do
        table.insert(MMSwidgetparams.widget.slotpos, Vector3(80 * x - 80 * 2 + 80, 80 * y - 80 * 2 + 80, 0))
    end
end

containers.MAXITEMSLOTS = math.max(containers.MAXITEMSLOTS, MMSwidgetparams.widget.slotpos ~= nil and #MMSwidgetparams.widget.slotpos or 0)

local function mywidgetsetup(container, prefab, data)
    local t = data or params[prefab or container.inst.prefab]
    if t ~= nil then
        for k, v in pairs(t) do
            container[k] = v
        end
        container:SetNumSlots(container.widget.slotpos ~= nil and #container.widget.slotpos or 0)
    end
end

function MMSwidgetparams.itemtestfn(container, item, slot) 
	-- local owner = item.components.inventoryitem and item.components.inventoryitem.owner
	-- if (owner ~= nil and owner:HasTag("player")) or (owner == nil and item.replica.inventoryitem and item.replica.inventoryitem:IsHeldBy(ThePlayer)) then
		-- return false -- We don't want the player to be able to put stuffs in this storage do we? We just want them to be able to collect what's in.
	-- else
		-- return true
	-- end
	return true
end

local function OnWidgetUpdate(inst)
	containers.widgetsetup = mywidgetsetup
    inst.replica.container:WidgetSetup(inst.prefab, MMSwidgetparams)
	containers.widgetsetup = prev_widgetsetup
	inst.replica.container.itemtestfn = function() return false end
end

-----------------------------------------------------------THE MACHINE ITSELF-----------------------------------------------------

local function GetMMStorage(inst)
	-- print("I check for an existing storage")

	local instposx, instposy, instposz = inst.Transform:GetWorldPosition()
	local nearbyents = TheSim:FindEntities(instposx, instposy, instposz,10, { "MnZmachines" , "storage" })
	
	local foundstorage = false
	for k, v in pairs(nearbyents) do
		-- print(k, " / ", v)
		if v:IsValid() then
			if inst.mmstorage == nil then
				inst.mmstorage = v
				v:SetFollowTarget(inst, "swap_storage", 0, 0, 0)
				v.AnimState:SetSortOrder(3)
				print("Existing storage found for", inst, ". Creating Link... ", inst.mmstorage)
				foundstorage = true
			else
				v.components.container:DropEverything()
				v:Remove()
				print("Duplicate found for", inst, ". Dumping content on the ground and deleting chest... ", inst.mmstorage)
			end		
		end
	end

	if not foundstorage then
		inst.mmstorage = SpawnPrefab("miningmachine_storage")
		inst.mmstorage.Transform:SetPosition(inst:GetPosition():Get())
		inst.mmstorage:SetFollowTarget(inst, "swap_storage", 0, 0, 0)
		inst.mmstorage.AnimState:SetSortOrder(3)
		print("No storage found for ", inst, ", I create a new one : ", inst.mmstorage)
	end
end

local function FillStorageWithSurpriseMob(inst, mob)
	local mms = inst.mmstorage
	local chestmobtable = mms.components.mnzmachines.surpriseinchest

	if chestmobtable[mob] == nil then
		chestmobtable[mob] = 1
	elseif chestmobtable[mob] < 3 then
		chestmobtable[mob] = chestmobtable[mob] + 1
	end
end

local function CheckForEscapeMobs(inst)	
	-- print("========= Check for a Mob Escape ============")
	local escmob_draw = math.random()
	
	if escmob_draw < TUNING.ESCMOBSODDS then
		-- print("A Mob Escaped!")
		local tiletype = TheWorld.Map:GetTileAtPoint(inst.Transform:GetWorldPosition())
		local closest_th = 2
		local mob_to_esc
		for k, v in pairs(MMLOOTTABLE["BIOME_"..tiletype]["ESCAPEMOBS"]) do
			if v < closest_th and v > escmob_draw/TUNING.ESCMOBSODDS then
				closest_th = v
				mob_to_esc = k
			end
		end
		
		local instx, insty, instz = inst.Transform:GetWorldPosition()
				
		local nearbyrocky = FindEntity(inst, 100, nil, { "rocky" })
		if nearbyrocky ~= nil then
			mob_to_esc = nil
		end
		
		-- print("A Mob Escaped! : ", mob_to_esc or "UNAVAILABLE")
		
		if mob_to_esc then
			local escmob = SpawnPrefab(mob_to_esc)
			escmob.Transform:SetPosition(instx + 3, insty + 3, instz)
		end
	end
end

local function StopDigging(inst)
	if inst.diggingtask ~= nil then
		inst.diggingtask:Cancel()
		inst.diggingtask = nil
	end
end

local function DiggingJob(inst)
	-- print("*********** I start the digging action ***********")
	-- print("Current Fuel Level = ", inst.components.fueled.currentfuel)
	
	if inst.components.fueled.currentfuel == 0 then
		inst.components.machine:TurnOff()
		return
	end
	
	math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) )
	
	local success_draw = math.random()
	if success_draw < TUNING.DIGSUCCESODDS then
		-- print("I digged successfully! :-)")
		
		local tiletype = TheWorld.Map:GetTileAtPoint(inst.Transform:GetWorldPosition())
		-- print("Tile Type is ", tiletype)

		local itemnumber = 0
		if success_draw < 0.175 then
			itemnumber = 1
		elseif success_draw > 0.525 then
			itemnumber = 3		
		else
			itemnumber = 2		
		end
		
		-- print("Amount of item to dig : ", itemnumber)
		
		local mms = inst.mmstorage
		
		for n = 1, itemnumber, 1 do
			-- print("----> ITEM # ", n)
			local tier_draw = math.random()
			local tier_loot
			
			if tier_draw <= MMLOOTTABLE["BIOME_"..tiletype].TIERONE.tierthreshold then
				tier_loot = "TIERONE"
			elseif tier_draw > MMLOOTTABLE["BIOME_"..tiletype].TIERONE.tierthreshold and tier_draw <= MMLOOTTABLE["BIOME_"..tiletype].TIERTWO.tierthreshold then
				tier_loot = "TIERTWO"	
			else
				tier_loot = "TIERTHREE"		
			end
			
			-- print("Random Tier Drawing = ", tier_draw, " <-> ", tier_loot)
			
			for n, m in pairs(MMLOOTTABLE["BIOME_"..tiletype][tier_loot]) do
				if n ~= "tierthreshold" then
					local current_minodd = 0
					for k, v in pairs(MMLOOTTABLE["BIOME_"..tiletype][tier_loot]) do
						if k ~= "tierthreshold" and v > current_minodd and v < m then
							current_minodd = v
						end
					end
					
					-- print("Probability to dig ", n, " = ", (m - current_minodd)  * 100, "%")
				end
			end
			
			local item_draw = math.random()
			local closest_th = 2
			local item_to_dig = nil
			for k, v in pairs(MMLOOTTABLE["BIOME_"..tiletype][tier_loot]) do
				if k ~= "tierthreshold" and v < closest_th and v > item_draw then
					closest_th = v
					item_to_dig = k
				end
			end
			
			-- print("---> Item to Dig  ", item_to_dig or "NOTHING!", " (draw = ", item_draw, ")")
			
			if item_to_dig then
				-- print("------> Storage = ", inst.mmstorage, "(found the container component : ", inst.mmstorage.components.container, ")")
				-- inst.components.lootdropper:SpawnLootPrefab(item_to_dig)
				local item_to_store = SpawnPrefab(item_to_dig)
				
				if tier_loot == "TIERONE" and item_to_store.components.stackable then
					local sstodig = math.random(1,3)
					item_to_store.components.stackable:SetStackSize(sstodig)
				end
				
				mms.components.container.itemtestfn = function() return true end
				local storeincontainer = mms.components.container:GiveItem(item_to_store, nil, nil, false)
				mms.components.container.itemtestfn =function() return false end
			end
		end
		
		local chestmob_draw = math.random()
			if mms.components.mnzmachines.surpriseinchest and chestmob_draw < TUNING.CHESTMOBSODDS then
				local closest_th = 2
				local mob_to_store = nil
				for k, v in pairs(MMLOOTTABLE["BIOME_"..tiletype]["CHESTMOBS"]) do
					if v < closest_th and v > chestmob_draw/TUNING.CHESTMOBSODDS then -- the division by the odd is to bring it back to a base of 1
						closest_th = v
						mob_to_store = k
					end
				end
				-- print("I brought a surprise with the loot : ", mob_to_store)
				if mob_to_store ~= "monkey" then -- monkeys seem buggy ATM
					FillStorageWithSurpriseMob(inst, mob_to_store)
				end
		end
	else
		if TheWorld.state.season == "summer" then
			if math.random() < ((TUNING.SUMMERJAMINC and TUNING.JAMODDS*2) or TUNING.JAMODDS) then
				-- print("Failed Digging Task : Machine Jammed!!")
				inst.components.mnzmachines.jammed = true 
			end
		else
			if math.random() < TUNING.JAMODDS then
				-- print("Failed Digging Task : Machine Jammed!!")
				inst.components.mnzmachines.jammed = true 
			end
		end
		
		CheckForEscapeMobs(inst)
	end
	
	-- print("I performed my digging action!")
end

local function SpawnSkeletonAtNight(inst)
	if TheWorld.state.isnight then
		local machinepos = inst:GetPosition()
		local nearbyskels = TheSim:FindEntities(machinepos.x, machinepos.y, machinepos.z, 35, { "mnzundeads" })
		inst.childrenskels = {}
		for k, v in pairs(nearbyskels) do
			if v:IsValid() then
				table.insert(inst.childrenskels, v.GUID)
			end
		end
		
		local skel_draw = math.random()
		-- print(inst, " is trying to spawn a skeleton : ", skel_draw, " (#skeletons around = ", #inst.childrenskels, ")")
		if skel_draw < 0.8 and #inst.childrenskels < 6 then
			local instpos = inst:GetPosition()
			local skel = SpawnPrefab("wonkyskeleton")
			skel.Transform:SetPosition(instpos.x + math.random(-6, 6), instpos.y, instpos.z + math.random(-6, 6))
			-- print("I spawned a skeleton for ", inst, " (number of children : ",inst.children and #inst.children,")")
		end
	end
end

local function InitializeDigging(inst)	
	if inst.diggingtask == nil then
		if TUNING.WINTERSLOWDOWN and TheWorld.state.season == "winter" then
			inst.diggingtask = inst:DoPeriodicTask(TUNING.SEG_TIME*16*1.4/TUNING.DIGPERIOD, DiggingJob)
			inst.AnimState:PushAnimation("mining_winter", true)
		else
			inst.diggingtask = inst:DoPeriodicTask(TUNING.SEG_TIME*16/TUNING.DIGPERIOD, DiggingJob)
			inst.AnimState:PushAnimation("mining", true)
		end
	end
	
	inst:DoTaskInTime(5, function()
							if inst.area then
								-- print(inst, " is positionned in a special area : ", inst.area)
								if inst.area == "graveyard" and inst.components.machine and inst.components.machine.ison then
									-- print("The machine will start spawning skeletons")
								inst:StopWatchingWorldState("isnight", SpawnSkeletonAtNight)
								inst:WatchWorldState("isnight", SpawnSkeletonAtNight)
								end
							end
						end
	)
end

local function TurnOff(inst, instant)
	-- print("Machine Turned Off!")
	inst.on = false
	inst.SoundEmitter:KillSound("miningsound")
	StopDigging(inst)
	
	inst.components.fueled:StopConsuming()
	inst.AnimState:PlayAnimation("idle")
	

	if inst.area then
		if inst.area == "graveyard" then
		-- print("machine stopped... Skeletons won't spawn before the machine is turned on again...")
		inst:StopWatchingWorldState("isnight", SpawnSkeletonAtNight)
		end
	end
	
	-- inst.sg:GoToState("turn_off")
end

local function TurnOn(inst, instant)
	inst.on = true
	
	if not inst:HasTag("jammed") then
		-- print("Machine Turned On!")
		InitializeDigging(inst)
		inst.components.fueled:StartConsuming()
		
		if TUNING.WINTERSLOWDOWN and TheWorld.state.iswinter then
			inst.AnimState:PlayAnimation("mining_winter", true)
		else
			inst.AnimState:PlayAnimation("mining", true)
		end
		
		if not inst.SoundEmitter:PlayingSound("miningsound") then
			inst.SoundEmitter:PlaySound("miningmachine/machine/mining", "miningsound")
		end
	end
	
	-- inst.sg:GoToState("turn_on")
end

local function onhammered(inst, worker)
	SpawnPrefab("collapse_small").Transform:SetPosition(inst.Transform:GetWorldPosition())
	
	if inst.prefab == "miningmachinekit" then
		inst.components.lootdropper:SpawnLootPrefab("miningmachinekit_item")
	elseif inst.prefab == "miningmachine" then
		for k, v in pairs(MMKINGREDIENTS) do
			for n = 1, math.ceil(v/2), 1 do
				inst.components.lootdropper:SpawnLootPrefab(k)
			end
		end
		if TUNING.KEEPREMAINS then
			local remains = SpawnPrefab("miningmachine_destroyed")
			remains.Transform:SetPosition(inst:GetPosition():Get())
		end
	end
	
	if inst.mmstorage ~= nil then
		inst.mmstorage.components.container:DropEverything()
		inst.mmstorage:Remove()
		inst.mmstorage = nil
	end
	
	inst:Remove()
end

local function OnSeasonChange(inst, data)
	StopDigging(inst)
	inst:DoTaskInTime(0.5, function()
								InitializeDigging(inst)
							end
					)
end

local function onsaveMM(inst, data)
	if inst.area ~= nil then
		data.area = inst.area
	end
end

local function onloadMM(inst, data)
	if inst.components.fueled and inst.components.fueled.currentfuel == 0 then
		inst.components.machine:TurnOff()
	end
	
	if data.area ~= nil then
		inst.area = data.area
	end
	
	inst:DoTaskInTime(2, function()
							if inst.components.machine.ison then
								if not inst.SoundEmitter:PlayingSound("miningsound") then
									inst.SoundEmitter:PlaySound("miningmachine/machine/mining", "miningsound")
								end
							end
							
							if inst.mmstorage and inst.mmstorage.components.container then
								inst.mmstorage.components.container.itemtestfn = function() return false end
							end
						end
	)
end

local function OnFuelEmpty(inst)
	-- print("I entered the OnFuelEmpty")
	inst.components.machine:TurnOff()
end

local function OnFuelSectionChange(new, old, inst)
	-- print("I entered the OnFuelSectionChanged")
    if inst._fuellevel ~= new then
        inst._fuellevel = new
        inst.AnimState:OverrideSymbol("swap_miningfuelmeter", "swap_miningfuelmeter", "swap_miningfuelmeter_"..new)
    end
end

local function OnSnowLevel(inst, snowlevel)
	if snowlevel > .02 then
		inst.AnimState:OverrideSymbol("snow", "snow", "snow")
	else
		inst.AnimState:OverrideSymbol("snow", "", "")
	end
end

local function getMMstatus(inst)
	return (inst:HasTag("fueldepleted") and "NOFUEL") or 
			(inst:HasTag("jammed") and "JAMMED") or
			(inst:HasTag("turnedon") and "MINING") or
			nil
end

local function miningmachinefn()
	local inst = CreateEntity()

	inst.entity:AddTransform()
	inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()
	inst.entity:AddMiniMapEntity()
	inst.entity:AddNetwork()

	MakeObstaclePhysics(inst, 1.6)
	
	inst.MiniMapEntity:SetIcon("miner_minimap.tex")
		
	-- inst.Transform:SetFourFaced()
	
	inst.AnimState:SetBank("miningmachine")
	inst.AnimState:SetBuild("miningmachine")
	if TUNING.WINTERSLOWDOWN and TheWorld.state.iswinter then
		inst.AnimState:PlayAnimation("mining_winter", true)
	else
		inst.AnimState:PlayAnimation("mining", true)
	end
    inst.AnimState:OverrideSymbol("swap_miningfuelmeter", "swap_miningfuelmeter", "swap_miningfuelmeter_8")
	inst.AnimState:OverrideSymbol("snow", "", "")
	
	inst:AddTag("structure")
	inst:AddTag("mining")
	
	inst.entity:SetPristine()

	if not TheWorld.ismastersim then
		return inst
	end

	inst:AddComponent("inspectable")
	inst.components.inspectable.getstatus = getMMstatus
	
	inst:AddComponent("machine")
	inst.components.machine.turnonfn = TurnOn
	inst.components.machine.turnofffn = TurnOff
	inst.components.machine.cooldowntime = 0.5
	
	inst:AddComponent("fueled")
	inst.components.fueled:SetDepletedFn(OnFuelEmpty)
	inst.components.fueled.accepting = true
	-- inst.components.fueled.ontakefuelfn = OnAddFuel
	inst.components.fueled.fueltype = FUELTYPE.BURNABLE
	inst.components.fueled.secondaryfueltype = FUELTYPE.CHEMICAL
	inst.components.fueled.bonusmult = 3.5
	inst.components.fueled:SetSections(8)
	inst.components.fueled:SetSectionCallback(OnFuelSectionChange)
	inst.components.fueled.maxfuel = TUNING.TOTAL_DAY_TIME*5
    inst.components.fueled:InitializeFuelLevel(TUNING.TOTAL_DAY_TIME*5)
	
	inst:AddComponent("lootdropper")
	
	inst:AddComponent("workable")
	inst.components.workable:SetWorkAction(ACTIONS.HAMMER)
	inst.components.workable:SetWorkLeft(5)
	inst.components.workable:SetOnFinishCallback(onhammered)
	-- inst.components.workable:SetOnWorkCallback(onhit)
	-- inst:ListenForEvent("onbuilt", onbuilt)
	
	inst:AddComponent("mnzmachines")
	inst:DoTaskInTime(0.5, GetMMStorage)
	inst.DiggingJob = DiggingJob
	inst.childrenskels = {}
	
	inst:WatchWorldState("season", OnSeasonChange)

	inst.OnSave = onsaveMM
	inst.OnLoad = onloadMM
	
	inst:WatchWorldState("snowlevel", OnSnowLevel)
    OnSnowLevel(inst, TheWorld.state.snowlevel)
	
	MakeHauntableLaunch(inst)
	
	return inst
end

---------------------------------------------------------------------STORAGE---------------------------------------------------------

local function AlignToOwner(inst)
    if inst.followtarget ~= nil then
		local ownerrot = inst.followtarget.Transform:GetRotation()
        inst.Transform:SetRotation(ownerrot)
    end
end

local function SetFollowTarget(inst, target, follow_symbol, follow_x, follow_y, follow_z)
	inst.followtarget = target
	if inst.followtarget ~= nil then
		inst.Follower:FollowSymbol(target.GUID, follow_symbol, follow_x, follow_y, follow_z)
		inst.savedfollowtarget = target
	elseif inst.savedfollowtarget ~= nil then
		inst:Remove()
	end
end

local function OnOpenMMS(inst)
	-- if TheWorld.ismastersim then print("Host Opened the storage ", inst) 
	-- else print("Client Opened the storage ", inst) end
	-- print("-> Found mnzmachines component : ", inst.components.mnzmachines)
	local surprisetable = inst.components.mnzmachines and inst.components.mnzmachines.surpriseinchest
	-- print("-> surpriseinchest exists : ", surprisetable)
	
	-- for k, v in pairs(surprisetable) do
		-- print(k, " / ", v)
	-- end
	
	if inst.components.mnzmachines and surprisetable then
		for k, v in pairs(surprisetable) do
			for n = 1, v, 1 do
				inst:DoTaskInTime(0.5, function()
											local surprisemob = SpawnPrefab(k)
											surprisemob.Transform:SetPosition(inst.Transform:GetWorldPosition())
										end
								)
			end
		end
		
		inst.components.mnzmachines.surpriseinchest = {}
	end
end

local widgetprops =
{
    "numslots",
    "acceptsstacks",
    "issidewidget",
    "type",
    "widget",
    "itemtestfn",
}

local function MMSWidgetSetupMod(self, prefab, data)
    for i, v in ipairs(widgetprops) do
        removesetter(self, v)
    end

    containers.widgetsetup(self, prefab, data)
    self.inst.replica.container:WidgetSetup(prefab, data)

    for i, v in ipairs(widgetprops) do
		if v ~= "itemtestfn" then
			makereadonly(self, v)
		end
    end
end

local function miningmachine_storagefn()
	local inst = CreateEntity()

	inst.entity:AddTransform()
	inst.entity:AddAnimState()
	inst.entity:AddFollower()
	inst.entity:AddNetwork()

	-- inst.Transform:SetFourFaced()
	
	inst.AnimState:SetBank("storage")
	inst.AnimState:SetBuild("miningmachine")
	inst.AnimState:PlayAnimation("idle")

	inst:AddTag("storage")
	
	inst._widgetupdate = net_bool(inst.GUID, "_widgetupdate", "onwidgetupdate")
	
	inst.entity:SetPristine()

	if not TheWorld.ismastersim then
	inst:ListenForEvent("onwidgetupdate", OnWidgetUpdate)
		return inst
	end

	inst:AddComponent("container")
	inst.components.container.WidgetSetup = MMSWidgetSetupMod
	containers.widgetsetup = mywidgetsetup
    inst.components.container:WidgetSetup(inst.prefab, MMSwidgetparams)
	containers.widgetsetup = prev_widgetsetup
	inst._widgetupdate:set(true)
	inst.components.container.onopenfn = OnOpenMMS
	
	inst:AddComponent("mnzmachines")
	
	inst.SetFollowTarget = SetFollowTarget
	-- inst:DoPeriodicTask(0, AlignToOwner)
	return inst
end

------------------------------------------------------------------------------KIT----------------------------------------------------

local function OnDeployMM(inst, pt, deployer)
	inst.Physics:Teleport(pt:Get())
	local deployedkit = SpawnPrefab("miningmachinekit")
	deployedkit.Physics:SetCollides(false)
	deployedkit.Transform:SetPosition(inst.Transform:GetWorldPosition())
	deployedkit.Physics:SetCollides(true)
	inst:Remove()	
	
	local machinepos = deployedkit:GetPosition()
	local surroundingents = TheSim:FindEntities(machinepos.x, machinepos.y, machinepos.z, 25, { "grave" })
	
	local nearbygraves = 0
	for k, v in pairs(surroundingents) do
		if v:IsValid() then
			nearbygraves = nearbygraves + 1
		end
	end
	if nearbygraves >= 2 then
		-- print("I am deploying the machine near a graveyard!")
		deployedkit.area = "graveyard"
	end
end

local validtiles = { GROUND.ROCKY , GROUND.DIRT, GROUND.SAVANNA , GROUND.GRASS , GROUND.FOREST , GROUND.MARSH , GROUND.CARPET , GROUND.DECIDUOUS , GROUND.DESERT_DIRT}

local function CanDeployMM(self, pt, mouseover)
	local candeploybase = TheWorld.Map:CanDeployAtPoint(pt, self.inst)
	
	local deploytile = TheWorld.Map:GetTileAtPoint(pt.x, 0, pt.z)
	-- print("Deploy Tile = ", deploytile)
	local groundcheck = false
	
	for k, v in pairs(validtiles) do
		if deploytile == v then
			groundcheck = true
			break
		end
	end
	
	local minspacingcheck = true
	local nearbyents = TheSim:FindEntities(pt.x, pt.y, pt.z, 25, { "MnZmachines" , "structure" })

	for k, v in pairs(nearbyents) do
		if v:IsValid() then
			minspacingcheck = false
			break
		end
	end
	
	return (candeploybase and groundcheck and minspacingcheck)
end

local function OnHostChangeCanDeploy(inst)
	if inst._hostcandeploy:value() ~= inst._clientcandeploy then	
		inst._clientcandeploy = inst._hostcandeploy:value()		
		inst.replica.inventoryitem.CanDeploy = CanDeployMM
	end
end

local function miningmachinekit_itemfn()
    local inst = CreateEntity()
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()
	
	MakeInventoryPhysics(inst)
     
    inst.AnimState:SetBank("kit")
    inst.AnimState:SetBuild("miningmachine")
    inst.AnimState:PlayAnimation("onground")

	inst.AnimState:SetScale(0.4,0.4,1)
 
	inst:AddTag("kit") -- Tag is not doing anything by itself. I can be called by other stuffs though.
	
 	inst._hostcandeploy = net_bool(inst.GUID, "_hostcandeploy", "onhostchangecandeploy")
	
 --The following section is suitable for a DST compatible prefab.
    inst.entity:SetPristine()
	
    if not TheWorld.ismastersim then	
		inst._clientcandeploy = nil
		inst:ListenForEvent("onhostchangecandeploy", OnHostChangeCanDeploy)
        return inst
    end
	
----------------------------------------------------------------

    inst:AddComponent("inspectable")
	
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.imagename = "miningmachinekit_item"
    inst.components.inventoryitem.atlasname = "images/inventory/miningmachinekit_item.xml"


    inst:AddComponent("deployable")
	
	inst.components.deployable.CanDeploy = CanDeployMM
	inst._hostcandeploy:set(true)
	inst.components.deployable.ondeploy = OnDeployMM

	inst:AddComponent("mnzmachines")
	
    MakeHauntableLaunch(inst)

	return inst
end

local function miningmachinekitfn()
    local inst = CreateEntity()
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
	inst.entity:AddMiniMapEntity()
    inst.entity:AddNetwork()
	
	MakeObstaclePhysics(inst, 1.8)

	inst.MiniMapEntity:SetIcon("minerkit_minimap.tex")
     
    inst.AnimState:SetBank("kit")
    inst.AnimState:SetBuild("miningmachine")
    inst.AnimState:PlayAnimation("idle")
	inst.AnimState:OverrideSymbol("snow", "", "")

 
	inst:AddTag("kit") -- Tag is not doing anything by itself. I can be called by other stuffs though.
	inst:AddTag("structure")
	
 --The following section is suitable for a DST compatible prefab.
    inst.entity:SetPristine()
	
    if not TheWorld.ismastersim then	
        return inst
    end
	
----------------------------------------------------------------

    inst:AddComponent("inspectable")
	
	inst:AddComponent("lootdropper")

	inst:AddComponent("workable")
	inst.components.workable:SetWorkAction(ACTIONS.HAMMER)
	inst.components.workable:SetWorkLeft(5)
	inst.components.workable:SetOnFinishCallback(onhammered)
	-- inst.components.workable:SetOnWorkCallback(onhit)
	-- inst:ListenForEvent("onbuilt", onbuilt)
	
	inst:AddComponent("mnzmachines")
	
	inst:WatchWorldState("snowlevel", OnSnowLevel)
    OnSnowLevel(inst, TheWorld.state.snowlevel)
	
    MakeHauntableLaunch(inst)

	return inst
end

local function miningmachine_destroyedfn()
    local inst = CreateEntity()
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
	inst.entity:AddMiniMapEntity()
    inst.entity:AddNetwork()
	
	MakeObstaclePhysics(inst, 0.8)
    
	inst.MiniMapEntity:SetIcon("minerdestroyed_minimap.tex")
	
    inst.AnimState:SetBank("miningmachine")
    inst.AnimState:SetBuild("miningmachine")
    inst.AnimState:PlayAnimation("destroyed")
	inst.AnimState:OverrideSymbol("snow", "", "")
 
	inst:AddTag("destroyed") -- Tag is not doing anything by itself. I can be called by other stuffs though.
	inst:AddTag("structure")
	
 --The following section is suitable for a DST compatible prefab.
    inst.entity:SetPristine()
	
    if not TheWorld.ismastersim then	
        return inst
    end
	
----------------------------------------------------------------

    inst:AddComponent("inspectable")
		
	inst:AddComponent("mnzmachines")
	
	inst:WatchWorldState("snowlevel", OnSnowLevel)
    OnSnowLevel(inst, TheWorld.state.snowlevel)
	
    MakeHauntableLaunch(inst)

	return inst
end

return  Prefab("common/machines/miningmachine", miningmachinefn, assets, prefabs),
		Prefab("common/machines/miningmachine_storage", miningmachine_storagefn, assets, prefabs),
		Prefab("common/machines/miningmachinekit", miningmachinekitfn, assets, prefabs),
		Prefab("common/machines/miningmachinekit_item", miningmachinekit_itemfn, assets, prefabs),
		MakePlacer("common/machines/miningmachinekit_item_placer", "kit", "miningmachine", "idle_placer"),
		Prefab("common/machines/miningmachine_destroyed", miningmachine_destroyedfn, assets, prefabs)

