if Mode=="\084\111\111\108"then AssignHotkey({"\076\101\102\116\067\111\110\116\114\111\108","\090"},History.Undo)AssignHotkey({"\082\105\103\104\116\067\111\110\116\114\111\108";"\090"},History.Undo)AssignHotkey({"\076\101\102\116\067\111\110\116\114\111\108","\089"},History.Redo)AssignHotkey({"\082\105\103\104\116\067\111\110\116\114\111\108","\089"},History.Redo)end function CloneSelection()if#Selection.Items==0 then return end local u=SyncAPI:Invoke("\067\108\111\110\101",Selection.Items)local k={Clones=u;Unapply=function(u)Selection.Remove(u.Clones,false)SyncAPI:Invoke("\082\101\109\111\118\101",u.Clones)end,Apply=function(u)SyncAPI:Invoke("\085\110\100\111\082\101\109\111\118\101",u.Clones)end}History.Add(k)Selection.Replace(u)PlayConfirmationSound();(coroutine.wrap(Selection.FlashOutlines))()end ConfirmationSound=(Create("\083\111\117\110\100"))({Name="\066\084\065\099\116\105\111\110\067\111\109\112\108\101\116\105\111\110\083\111\117\110\100",Pitch=1.5,SoundId=Assets.ActionCompletionSound,Volume=1})function PlayConfirmationSound()SoundService:PlayLocalSound(ConfirmationSound)end function DeleteSelection()local u={Parts=Support.CloneTable(Selection.Items);Unapply=function(u)SyncAPI:Invoke("\085\110\100\111\082\101\109\111\118\101",u.Parts)Selection.Replace(u.Parts)end;Apply=function(u)Selection.Remove(u.Parts,false)SyncAPI:Invoke("\082\101\109\111\118\101",u.Parts)end}Selection.Remove(u.Parts,false)SyncAPI:Invoke("\082\101\109\111\118\101",u.Parts)History.Add(u)end

if Mode == 'Tool' then
	AssignHotkey({ 'LeftControl', 'Z' }, History.Undo);
	AssignHotkey({ 'RightControl', 'Z' }, History.Undo);
	AssignHotkey({ 'LeftControl', 'Y' }, History.Redo);
	AssignHotkey({ 'RightControl', 'Y' }, History.Redo);
end;

function CloneSelection()
	-- Clones selected parts

	-- Make sure that there are items in the selection
	if #Selection.Items == 0 then
		return;
	end;

	-- Send the cloning request to the server
	local Clones = SyncAPI:Invoke('Clone', Selection.Items);

	-- Put together the history record
	local HistoryRecord = {
		Clones = Clones;

		Unapply = function (HistoryRecord)
			-- Reverts this change

			-- Deselect the clones
			Selection.Remove(HistoryRecord.Clones, false);

			-- Remove the clones
			SyncAPI:Invoke('Remove', HistoryRecord.Clones);

		end;

		Apply = function (HistoryRecord)
			-- Reapplies this change

			-- Restore the clones
			SyncAPI:Invoke('UndoRemove', HistoryRecord.Clones);

		end;

	};

	-- Register the history record
	History.Add(HistoryRecord);

	-- Select the clones
	Selection.Replace(Clones);

	-- Play a confirmation sound
	PlayConfirmationSound();

	-- Flash the outlines of the new parts
	coroutine.wrap(Selection.FlashOutlines)();

end;

ConfirmationSound = Create 'Sound' {
	Name = 'BTActionCompletionSound';
	Pitch = 1.5;
	SoundId = Assets.ActionCompletionSound;
	Volume = 1;
};

function PlayConfirmationSound()
	-- Plays a confirmation beep sound

	-- Trigger the sound locally
	SoundService:PlayLocalSound(ConfirmationSound);

end;

function DeleteSelection()
	-- Deletes selected items

	-- Put together the history record
	local HistoryRecord = {
		Parts = Support.CloneTable(Selection.Items);

		Unapply = function (HistoryRecord)
			-- Reverts this change

			-- Restore the parts
			SyncAPI:Invoke('UndoRemove', HistoryRecord.Parts);

			-- Select the restored parts
			Selection.Replace(HistoryRecord.Parts);

		end;

		Apply = function (HistoryRecord)
			-- Applies this change

			-- Deselect the parts
			Selection.Remove(HistoryRecord.Parts, false);

			-- Remove the parts
			SyncAPI:Invoke('Remove', HistoryRecord.Parts);

		end;

	};

	-- Deselect parts before deleting
	Selection.Remove(HistoryRecord.Parts, false);

	-- Perform the removal
	SyncAPI:Invoke('Remove', HistoryRecord.Parts);

	-- Register the history record
	History.Add(HistoryRecord);

end;
