Проблемы начинаются не только при читерстве, но и банально при обрыве связи с сервером. Например, когда у пользователя пропадает Интернет. И если вы разрешаете игроку перемещаться локально, отсылая координаты, то с точки зрения сервера игрок исчезнет на некоторое время, а потом появится в других координатах, далеких от тех, где он был.
На самом деле здесь есть много нюансов, поэтому универсального рецепта нет. Зависит от вашей игры. Например, если игра очень динамична, то на клиенте должно быть обязательно сглаживание. Ведь будет убого выглядеть, если после нажатия W пройдет 200мс, и только затем квадратик сдвинется. Нужно, чтобы он двигался сразу, а уж потом, если вдруг это оказалось неправомерным, сервер может прислать новые координаты и оттелепортировать игрока назад. И наоборот, если игра медленная и неповоротливая (например, пошаговая), то выгоднее перепроверять каждый чих пользователя перед тем, как отобразить действие на экране у него и всех остальных.
Есть даже гибридные, так называемые арбитражные системы, когда клиенты проверяют клиентов и голосуют за то, что кто-то читер, а сервер ни при чем, он просто реагирует на рассинхрон, подтвержденный статистически. Но это сложно сделать, и полезно только для высоконагруженных серверов, чтобы их разгрузить.
В вашем случае, я так понимаю, высокая нагрузка не планируется. Так что можно поступать также, как и всегда при разработке сайтов. А именно -
никогда не доверять клиенту. Он может послать какие угодно данные. И нужно их проверять и перепроверять постоянно, чтобы избиваться как от читерства, так и от банальных ошибок в коде на клиенте.
Что касается того, что игрок может у себя поменять какие-то данные, приходящие от сервера, то это не должно касаться других игроков. Да, игрок сможет нарисовать себе миллион долларов и переместить себя за стену, изменив координаты локально. Но на сервере это должно игнорироваться. То есть сервер должен посчитать, что игрок не мог туда попасть, и блокировать все попытки действий в той области. Как посчитать - это уже зависит от игры, от логики геймплея. Например, у игрока было слишком мало времени, чтобы преодолеть такое расстояние (считаем путь обхода стены).
Если говорить про чисто техническую защиту от изменения кода на клиенет, то лучшее, что вы можете сделать, это обернуть весь код в анонимную функцию. Она будет как бы глобальным пространством для других функций и переменных, но через консоль к ней нельзя будет получить доступ.
(function() {
let x = 50;
let y = 50;
// и т.д. всё, как обычно, только в обертке
})();
Однако настоящих прошареных хакеров такой метод не остановит, конечно. Большинство пользователей - да, но единицы смогут это обойти, меняя непосредственно сетевые пакеты, приходящие в браузер. Именно поэтому нужно валидизировать все поступающие на сервер данные, чтобы их нельзя было подделать.