diff --git a/client/build.sh b/client/build.sh index d0b5e75..f614120 100755 --- a/client/build.sh +++ b/client/build.sh @@ -6,4 +6,10 @@ cat dest/block.js >> dest/script.js cat dest/network.js >> dest/script.js cat dest/player.js >> dest/script.js cat dest/core.js >> dest/script.js -terser dest/script.js -o dest/script.min.js --compress --mangle \ No newline at end of file +terser dest/script.js -o dest/script.min.js --compress --mangle +rm dest/script.js +rm dest/main.js +rm dest/block.js +rm dest/network.js +rm dest/player.js +rm dest/core.js \ No newline at end of file diff --git a/client/dest/block.js b/client/dest/block.js deleted file mode 100644 index 3156695..0000000 --- a/client/dest/block.js +++ /dev/null @@ -1,112 +0,0 @@ -class Block { - constructor(x, y, color, collides, type) { - this.x = x; - this.y = y; - this.color = color; - this.collides = collides; - this.type = type; - } - render() { - let rect = this.translate_to_camera(); - if (this.is_need_render(rect)) { - ctx.fillStyle = this.color; - ctx.fillRect(...rect); - } - } - is_need_render(rect) { - return rect[0] + rect[2] > 0 || rect[1] + rect[3] > 0 || rect[0] < width || rect[1] < height; - } - translate_to_camera() { - let size = camera.size * 16; - return [ - this.x * size - size / 2 + (width / 2 - camera.x * size), - height - (this.y + 1) * size + size / 2 - (height / 2 - camera.y * size), - size, - size - ]; - } - tick() { - } - renderTick() { - } - on_collide(player, x, y) { - if (x != 0) - player.velocity_x = this.x + x - player.x; - if (y != 0) - player.velocity_y = this.y + y - player.y; - } - renderText() { - } -} -class Player extends Block { - constructor(x, y, name, color, velocity_x, velocity_y) { - super(x, y, color, true, null); - this.velocity_x = velocity_x; - this.velocity_y = velocity_y; - this.name = name; - } - reset() { - this.on_ground = false; - } - on_collide(player, x, y) { - super.on_collide(player, x, y); - } - tick(collide = true) { - this.x = Math.round(this.x * 100) / 100; - this.y = Math.round(this.y * 100) / 100; - this.velocity_x = Math.round(this.velocity_x * 100) / 100; - this.velocity_y = Math.round(this.velocity_y * 100) / 100; - if (collide) - this.collide(); - } - collide() { - this.on_ground = false; - for (const block of blocks) { - if (!block.collides) - continue; - let collide_x = 0; - let collide_y = 0; - if (this.x > block.x - 1 && this.x < block.x + 1) { - if (this.y > block.y && this.y + this.velocity_y - 1 < block.y) { - this.on_ground = true; - collide_y = 1; - } - if (this.y < block.y && this.y + this.velocity_y > block.y - 1) - collide_y = -1; - } - if (this.y > block.y - 1 && this.y < block.y + 1) { - if (this.x > block.x && this.x + this.velocity_x - 1 < block.x) - collide_x = 1; - if (this.x < block.x && this.x + this.velocity_x > block.x - 1) - collide_x = -1; - } - block.on_collide(this, collide_x, collide_y); - } - } - renderTick() { - this.velocity_x *= 0.5; - this.velocity_y *= 0.5; - this.x += this.velocity_x; - this.y += this.velocity_y; - } - renderText() { - super.renderText(); - let rect = this.translate_to_camera(); - if (this.is_need_render(rect)) { - ctx.fillStyle = "#ddd"; - ctx.font = "15px monospace"; - let width = ctx.measureText(this.name).width; - ctx.fillText(this.name, rect[0] + rect[2] / 2 - width / 2, rect[1] - 5); - } - } - teleport(x, y) { - this.velocity_x = x - this.x; - this.velocity_y = y - this.y; - } - forceTeleport(x, y) { - this.x = x; - this.y = y; - this.velocity_x = 0; - this.velocity_y = 0; - } -} diff --git a/client/dest/core.js b/client/dest/core.js deleted file mode 100644 index 7ba3ef0..0000000 --- a/client/dest/core.js +++ /dev/null @@ -1,90 +0,0 @@ -var ticksAlive = 0; -var debugMode = false; -var camera = { - x: 0.0, - y: 0.0, - size: 1.5 -}; -var chatOpened = false; -var chatMessages = []; -var chatTyping = ""; -var player = new MainPlayer(); -player.register(); -var blocks = []; -const allowed_key_to_send = [ - "KeyR", "KeyW", "KeyE", "KeyQ", "KeyS", - "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", - "Numpad6", "Numpad7", "Numpad8", "Numpad9", "Numpad0", - "ShiftLeft", "ControlLeft", "Enter", - "F1", "F2", "KeyZ", "KeyX", "KeyC" -]; -function connectServer(address, name) { - player.closeConnection(); - player.onConnect(name); - try { - let conn = new Connection(address, player.onPacket, (e) => { - player.conn = null; - setServerError(e == null ? "Connection closed due to error" : e); - resetWorld(); - }); - conn.send(new JoinPacket(name)); - } - catch (exception) { - setServerError(exception); - } -} -function resetWorld() { - player.onConnect("unnamed player"); - blocks = []; - blocks.push(new Block(-1, -1, "#555", true, "normal")); - blocks.push(new Block(0, -1, "#a67", true, "spawn")); - blocks.push(new Block(1, -1, "#555", true, "normal")); -} -function getBlock(x, y) { - let value = blocks.find(o => !(o instanceof Player) && o.x == x && o.y == y); - if (typeof value === "undefined") { - return null; - } - else { - return value; - } -} -function placeBlock(block) { - blocks.push(block); -} -function removeBlock(x, y) { - blocks = blocks.filter(o => o instanceof Player || o.x != x || o.y != y); -} -function getPlayer(name) { - let value = blocks.find(o => o instanceof Player && o.name == name); - if (typeof value === "undefined") { - return null; - } - else { - return value; - } -} -function removePlayer(name) { - blocks = blocks.filter(o => !(o instanceof Player) || o.name != name); -} -function render() { - ctx.fillStyle = "#333"; - ctx.fillRect(0, 0, width, height); - for (const block of blocks) - block.render(); - for (const block of blocks) - block.renderText(); - player.render(); - player.renderText(); -} -function tick() { - for (const block of blocks) - block.tick(); - player.tick(); -} -function renderTick() { - for (const block of blocks) - block.renderTick(); - player.renderTick(); -} -resetWorld(); diff --git a/client/dest/main.js b/client/dest/main.js deleted file mode 100644 index 7108b87..0000000 --- a/client/dest/main.js +++ /dev/null @@ -1,53 +0,0 @@ -const canvas = document.getElementById("game"); -const ctx = canvas.getContext("2d"); -const width = 640; -const height = 480; -const server_ip = document.getElementById("server-ip"); -const server_nick = document.getElementById("server-nick"); -const connect_server = document.getElementById("connect-server"); -const server_error = document.getElementById("server-error"); -function wrapText(ctx, text, maxWidth) { - const lines = []; - let currentLine = ''; - for (let i = 0; i < text.length; i++) { - const char = text[i]; - const testLine = currentLine + char; - const testWidth = ctx.measureText(testLine).width; - if (testWidth > maxWidth && currentLine) { - lines.push(currentLine); - currentLine = char; - } - else { - currentLine = testLine; - } - } - if (currentLine) { - lines.push(currentLine); - } - return lines; -} -function lerp(a, b, alpha) { - return a + alpha * (b - a); -} -function setServerError(text) { - server_error.innerText = text; -} -connect_server.onclick = () => { - let ip = server_ip.value; - let nick = server_nick.value; - setServerError(""); - if (ip.length == 0) - return setServerError("введите айпи пж"); - if (nick.length == 0) - return setServerError("введите ник пж"); - if (!ip.includes(":")) - ip += ":8000"; - connectServer(ip, nick); -}; -setInterval(tick, 1000 / 20); -setInterval(renderTick, 1000 / 60); -let renderTimer = () => { - render(); - requestAnimationFrame(renderTimer); -}; -requestAnimationFrame(renderTimer); diff --git a/client/dest/network.js b/client/dest/network.js deleted file mode 100644 index 85521bf..0000000 --- a/client/dest/network.js +++ /dev/null @@ -1,71 +0,0 @@ -class Packet { - constructor(id, data) { - this.id = id; - this.data = data; - } - getId() { return this.id; } - getData() { return this.data; } - static fromString(data) { - return new Packet(data[0], data.slice(1).split("\n")); - } -} -class JoinPacket extends Packet { - constructor(name) { - super("J", [name]); - } -} -class MessagePacket extends Packet { - constructor(message) { - super("M", [message]); - } -} -class KeyPacket extends Packet { - constructor(key, pressed) { - super("K", [key, pressed ? "1" : "0"]); - } -} -class PlaceBlockPacket extends Packet { - constructor(x, y, type) { - super("P", [x.toString(), y.toString(), type]); - } -} -class DestroyBlockPacket extends Packet { - constructor(x, y) { - super("D", [x.toString(), y.toString()]); - } -} -class PositionPacket extends Packet { - constructor(x, y) { - super("X", [x.toString(), y.toString()]); - } -} -class VelocityPacket extends Packet { - constructor(x, y) { - super("V", [x.toString(), y.toString()]); - } -} -class Connection { - constructor(address, on_packet, on_close) { - this.socket = new WebSocket("ws://" + address, "cubic"); - this.on_packet = on_packet; - this.on_close = on_close; - this.socket.onmessage = this._on_message; - this.socket.onclose = this._on_close; - this.socket.onerror = this._on_error; - } - _on_message(event) { - this.on_packet(Packet.fromString(event.data)); - } - _on_close(event) { - this.on_close(null); - } - _on_error(event) { - this.on_close(event.toString()); - } - close() { - this.socket.close(); - } - send(packet) { - this.socket.send(packet.getId() + packet.getData()); - } -} diff --git a/client/dest/player.js b/client/dest/player.js deleted file mode 100644 index d34f0e8..0000000 --- a/client/dest/player.js +++ /dev/null @@ -1,347 +0,0 @@ -class MainPlayer extends Player { - constructor() { - super(0.0, 0.0, "unnamed player", "#5e6", 0, 0); - this.reset(); - this.conn = null; - } - reset() { - super.reset(); - this.walk_speed = 1; - this.jump_speed = 2; - this.gravity_speed = 0.5; - this.controls_x = 0; - this.controls_jump = false; - this.block_type = null; - this.all_block_types = [ - "normal", "normal", "normal", "normal", "normal", - "normal", "normal", "normal", "normal", "normal" - ]; - } - onConnect(name) { - this.x = 0.0; - this.y = 0.0; - this.velocity_x = 0.0; - this.velocity_y = 0.0; - camera.x = 0.0; - camera.y = 0.0; - chatOpened = false; - chatMessages = []; - this.name = name; - this.color = "#5e6"; - blocks = []; - this.reset(); - } - register() { - document.addEventListener("keydown", (e) => { - let key = e.code; - if (chatOpened) { - if (key == "Backspace") { - chatTyping = chatTyping.slice(0, chatTyping.length - 1); - } - else if (key == "Enter") { - if (chatTyping == "") { - chatOpened = false; - return; - } - this.sendPacket(new MessagePacket(chatTyping)); - chatTyping = ""; - chatOpened = false; - } - else if (key == "Escape") { - chatOpened = false; - } - else if (e.key.length == 1) { - chatTyping += e.key; - e.preventDefault(); - return false; - } - } - else { - if (key == "KeyD") { - this.controls_x = 1; - } - else if (key == "KeyA") { - this.controls_x = -1; - } - else if (key == "Space") { - this.controls_jump = true; - e.preventDefault(); - return false; - } - else if (key == "KeyR") { - if (this.conn == null) { - this.forceTeleport(0, 1); - } - } - else if (key == "KeyT") { - chatOpened = true; - } - if (e.key == "0") - this.block_type = null; - if ("123456789".includes(e.key)) - this.block_type = this.all_block_types[parseInt(e.key) - 1]; - if (allowed_key_to_send.includes(key)) { - this.sendPacket(new KeyPacket(key, true)); - } - if (key == "Escape") { - this.closeConnection(); - } - } - if (key == "F3") { - debugMode = !debugMode; - e.preventDefault(); - return false; - } - }); - document.addEventListener("keyup", (e) => { - let key = e.code; - if ((key == "KeyD" && this.controls_x == 1) - || (key == "KeyA" && this.controls_x == -1)) { - this.controls_x = 0; - } - else if (key == "Space" && this.controls_jump) { - this.controls_jump = false; - } - if (allowed_key_to_send.includes(key)) { - this.sendPacket(new KeyPacket(key, false)); - } - }); - canvas.addEventListener("wheel", e => { - if (e.deltaY > 0) { - camera.size *= 0.5 * (e.deltaY / 114); - } - else { - camera.size *= 2 * (e.deltaY / -114); - } - e.preventDefault(); - return false; - }); - canvas.addEventListener("mousedown", e => { - let rect = canvas.getBoundingClientRect(); - let size = 16 * camera.size; - let x = Math.round((e.clientX - rect.x) / size - (width / size / 2) + camera.x); - let y = Math.round((height - (e.clientY - rect.y)) / size - (height / size / 2) + camera.y); - if (e.buttons == 2 && this.block_type != null) { - if (this.conn == null) { - placeBlock(new Block(x, y, "#555", true, this.block_type)); - } - this.sendPacket(new PlaceBlockPacket(x, y, this.block_type)); - } - else if (e.buttons == 1) { - if (this.conn == null) { - removeBlock(x, y); - } - this.sendPacket(new DestroyBlockPacket(x, y)); - } - }); - } - sendPacket(packet) { - if (this.conn != null) { - this.conn.send(packet); - } - } - closeConnection() { - if (this.conn != null) - this.conn.close(); - this.conn = null; - } - onPacket(packet) { - let packet_id = packet.getId(); - let packet_data = packet.getData(); - if (packet_id == "K") { - setServerError(packet_data[0]); - this.closeConnection(); - } - if (packet_id == "N") { - this.name = packet_data[0]; - } - if (packet_id == "C") { - this.color = packet_data[0]; - } - if (packet_id == "M") { - chatMessages.unshift(...packet_data); - } - if (packet_id == "R") { - this.velocity_x = parseFloat(packet_data[0]) - this.x + parseFloat(packet_data[2]); - this.velocity_y = parseFloat(packet_data[1]) - this.y + parseFloat(packet_data[3]); - } - if (packet_id == "P") { - let x = parseFloat(packet_data[0]); - let y = parseFloat(packet_data[1]); - this.x = x; - this.y = y; - } - if (packet_id == "V") { - let x = parseFloat(packet_data[0]); - let y = parseFloat(packet_data[1]); - this.velocity_x = x; - this.velocity_y = y; - } - if (packet_id == "S") { - let speed_type = packet_data[0]; - let speed = parseFloat(packet_data[1]); - if (speed_type == "W") { - this.walk_speed = speed; - } - else if (speed_type == "J") { - this.jump_speed = speed; - } - else if (speed_type == "G") { - this.gravity_speed = speed; - } - } - if (packet_id == "W") { - for (const data of packet_data) { - let type = data[0]; - let create = data[1] == "1"; - let params = data.slice(2).split(","); - if (type == "B") { - let x = parseFloat(params[0]); - let y = parseFloat(params[1]); - if (create) { - let collides = params[2] == "1"; - let type = params[3]; - let color = params[4]; - let block = getBlock(x, y); - if (block != null) { - block.x = x; - block.y = y; - block.color = color; - block.collides = collides; - block.type = type; - } - else { - placeBlock(new Block(x, y, color, collides, type)); - } - } - else { - removeBlock(x, y); - } - } - else if (type == "P") { - let name = params[0]; - if (create) { - let x = parseFloat(params[1]); - let y = parseFloat(params[2]); - let vel_x = parseFloat(params[3]); - let vel_y = parseFloat(params[4]); - let color = params[5]; - let player = getPlayer(name); - if (player != null) { - player.x = x; - player.y = y; - player.color = color; - player.velocity_x = vel_x; - player.velocity_y = vel_y; - } - else { - placeBlock(new Player(x, y, name, color, vel_x, vel_y)); - } - } - else { - removePlayer(name); - } - } - } - } - if (packet_id == "B") { - this.all_block_types = packet_data.slice(0, 9); - this.block_type = null; - } - } - tick() { - super.tick(false); - let vel_x = this.velocity_x; - let vel_y = this.velocity_y; - this.velocity_x += this.controls_x * this.walk_speed; - if (this.controls_jump && this.on_ground) { - this.velocity_y += this.jump_speed; - this.on_ground = false; - } - else { - this.velocity_y -= this.gravity_speed; - } - this.collide(); - ticksAlive++; - this.sendPacket(new VelocityPacket(this.velocity_x - vel_x, this.velocity_y - vel_y)); - this.sendPacket(new PositionPacket(this.x, this.y)); - } - render() { - super.render(); - camera.x = Math.round(lerp(camera.x, this.x, 0.075) * 1000) / 1000; - camera.y = Math.round(lerp(camera.y, this.y, 0.075) * 1000) / 1000; - } - renderText() { - super.renderText(); - if (this.block_type != null) { - ctx.fillStyle = "#76d"; - ctx.font = "15px monospace"; - ctx.fillText("selected: " + this.block_type, 0, 15); - } - if (debugMode) { - ctx.fillStyle = "#de7"; - ctx.font = "20px monospace"; - ctx.fillText("x: " + this.x, 0, 20); - ctx.fillText("y: " + this.y, 0, 40); - ctx.fillText("velocity_x: " + this.velocity_x, 0, 60); - ctx.fillText("velocity_y: " + this.velocity_y, 0, 80); - ctx.fillText("camera.x: " + camera.x, 0, 100); - ctx.fillText("camera.y: " + camera.y, 0, 120); - } - if (!chatOpened) { - ctx.fillStyle = "#22222288"; - ctx.fillRect(5, height - 35, width * 0.4, 30); - ctx.fillStyle = "#aaaaaa88"; - ctx.font = "15px monospace"; - ctx.fillText("Нажмите T для чата", 15, height - 15); - } - else { - ctx.fillStyle = "#22222288"; - ctx.fillRect(5, height - 35, width - 10, 30); - ctx.save(); - ctx.beginPath(); - ctx.moveTo(5, height - 35); - ctx.lineTo(width - 5, height - 35); - ctx.lineTo(width - 5, height - 5); - ctx.lineTo(5, height - 5); - ctx.lineTo(5, height - 35); - ctx.closePath(); - ctx.clip(); - ctx.font = "15px monospace"; - if (chatTyping.length == 0) { - ctx.fillStyle = "#aaaaaa88"; - ctx.fillText("Напишите сообщение...", 15, height - 15); - } - else { - ctx.fillStyle = "#ffffff"; - let text_width = ctx.measureText(chatTyping).width; - ctx.fillText(chatTyping, Math.min(10, width - text_width - 10), height - 15); - } - ctx.restore(); - } - if (chatMessages.length > 0) { - let draw_message = (message) => { - let lines = wrapText(ctx, message, message_width - 20); - let height = lines.length * 20 + 5 + 5; - let top = message_bottom - height; - ctx.fillStyle = "#22222288"; - ctx.fillRect(5, top, message_width, height); - let y = 5; - for (let line of lines) { - ctx.fillStyle = "#ffffff"; - ctx.fillText(line, 15, top + y + 15); - y += 5 + 20; - } - message_bottom -= height + 5; - }; - let message_width = width * 0.4; - let message_bottom = height - 35 - 5; - if (chatOpened) { - chatMessages.forEach(draw_message); - } - else { - draw_message(chatMessages[0]); - } - } - } -} diff --git a/client/dest/script.js b/client/dest/script.js deleted file mode 100644 index e4e3d25..0000000 --- a/client/dest/script.js +++ /dev/null @@ -1,673 +0,0 @@ -const canvas = document.getElementById("game"); -const ctx = canvas.getContext("2d"); -const width = 640; -const height = 480; -const server_ip = document.getElementById("server-ip"); -const server_nick = document.getElementById("server-nick"); -const connect_server = document.getElementById("connect-server"); -const server_error = document.getElementById("server-error"); -function wrapText(ctx, text, maxWidth) { - const lines = []; - let currentLine = ''; - for (let i = 0; i < text.length; i++) { - const char = text[i]; - const testLine = currentLine + char; - const testWidth = ctx.measureText(testLine).width; - if (testWidth > maxWidth && currentLine) { - lines.push(currentLine); - currentLine = char; - } - else { - currentLine = testLine; - } - } - if (currentLine) { - lines.push(currentLine); - } - return lines; -} -function lerp(a, b, alpha) { - return a + alpha * (b - a); -} -function setServerError(text) { - server_error.innerText = text; -} -connect_server.onclick = () => { - let ip = server_ip.value; - let nick = server_nick.value; - setServerError(""); - if (ip.length == 0) - return setServerError("введите айпи пж"); - if (nick.length == 0) - return setServerError("введите ник пж"); - if (!ip.includes(":")) - ip += ":8000"; - connectServer(ip, nick); -}; -setInterval(tick, 1000 / 20); -setInterval(renderTick, 1000 / 60); -let renderTimer = () => { - render(); - requestAnimationFrame(renderTimer); -}; -requestAnimationFrame(renderTimer); -class Block { - constructor(x, y, color, collides, type) { - this.x = x; - this.y = y; - this.color = color; - this.collides = collides; - this.type = type; - } - render() { - let rect = this.translate_to_camera(); - if (this.is_need_render(rect)) { - ctx.fillStyle = this.color; - ctx.fillRect(...rect); - } - } - is_need_render(rect) { - return rect[0] + rect[2] > 0 || rect[1] + rect[3] > 0 || rect[0] < width || rect[1] < height; - } - translate_to_camera() { - let size = camera.size * 16; - return [ - this.x * size - size / 2 + (width / 2 - camera.x * size), - height - (this.y + 1) * size + size / 2 - (height / 2 - camera.y * size), - size, - size - ]; - } - tick() { - } - renderTick() { - } - on_collide(player, x, y) { - if (x != 0) - player.velocity_x = this.x + x - player.x; - if (y != 0) - player.velocity_y = this.y + y - player.y; - } - renderText() { - } -} -class Player extends Block { - constructor(x, y, name, color, velocity_x, velocity_y) { - super(x, y, color, true, null); - this.velocity_x = velocity_x; - this.velocity_y = velocity_y; - this.name = name; - } - reset() { - this.on_ground = false; - } - on_collide(player, x, y) { - super.on_collide(player, x, y); - } - tick(collide = true) { - this.x = Math.round(this.x * 100) / 100; - this.y = Math.round(this.y * 100) / 100; - this.velocity_x = Math.round(this.velocity_x * 100) / 100; - this.velocity_y = Math.round(this.velocity_y * 100) / 100; - if (collide) - this.collide(); - } - collide() { - this.on_ground = false; - for (const block of blocks) { - if (!block.collides) - continue; - let collide_x = 0; - let collide_y = 0; - if (this.x > block.x - 1 && this.x < block.x + 1) { - if (this.y > block.y && this.y + this.velocity_y - 1 < block.y) { - this.on_ground = true; - collide_y = 1; - } - if (this.y < block.y && this.y + this.velocity_y > block.y - 1) - collide_y = -1; - } - if (this.y > block.y - 1 && this.y < block.y + 1) { - if (this.x > block.x && this.x + this.velocity_x - 1 < block.x) - collide_x = 1; - if (this.x < block.x && this.x + this.velocity_x > block.x - 1) - collide_x = -1; - } - block.on_collide(this, collide_x, collide_y); - } - } - renderTick() { - this.velocity_x *= 0.5; - this.velocity_y *= 0.5; - this.x += this.velocity_x; - this.y += this.velocity_y; - } - renderText() { - super.renderText(); - let rect = this.translate_to_camera(); - if (this.is_need_render(rect)) { - ctx.fillStyle = "#ddd"; - ctx.font = "15px monospace"; - let width = ctx.measureText(this.name).width; - ctx.fillText(this.name, rect[0] + rect[2] / 2 - width / 2, rect[1] - 5); - } - } - teleport(x, y) { - this.velocity_x = x - this.x; - this.velocity_y = y - this.y; - } - forceTeleport(x, y) { - this.x = x; - this.y = y; - this.velocity_x = 0; - this.velocity_y = 0; - } -} -class Packet { - constructor(id, data) { - this.id = id; - this.data = data; - } - getId() { return this.id; } - getData() { return this.data; } - static fromString(data) { - return new Packet(data[0], data.slice(1).split("\n")); - } -} -class JoinPacket extends Packet { - constructor(name) { - super("J", [name]); - } -} -class MessagePacket extends Packet { - constructor(message) { - super("M", [message]); - } -} -class KeyPacket extends Packet { - constructor(key, pressed) { - super("K", [key, pressed ? "1" : "0"]); - } -} -class PlaceBlockPacket extends Packet { - constructor(x, y, type) { - super("P", [x.toString(), y.toString(), type]); - } -} -class DestroyBlockPacket extends Packet { - constructor(x, y) { - super("D", [x.toString(), y.toString()]); - } -} -class PositionPacket extends Packet { - constructor(x, y) { - super("X", [x.toString(), y.toString()]); - } -} -class VelocityPacket extends Packet { - constructor(x, y) { - super("V", [x.toString(), y.toString()]); - } -} -class Connection { - constructor(address, on_packet, on_close) { - this.socket = new WebSocket("ws://" + address, "cubic"); - this.on_packet = on_packet; - this.on_close = on_close; - this.socket.onmessage = this._on_message; - this.socket.onclose = this._on_close; - this.socket.onerror = this._on_error; - } - _on_message(event) { - this.on_packet(Packet.fromString(event.data)); - } - _on_close(event) { - this.on_close(null); - } - _on_error(event) { - this.on_close(event.toString()); - } - close() { - this.socket.close(); - } - send(packet) { - this.socket.send(packet.getId() + packet.getData()); - } -} -class MainPlayer extends Player { - constructor() { - super(0.0, 0.0, "unnamed player", "#5e6", 0, 0); - this.reset(); - this.conn = null; - } - reset() { - super.reset(); - this.walk_speed = 1; - this.jump_speed = 2; - this.gravity_speed = 0.5; - this.controls_x = 0; - this.controls_jump = false; - this.block_type = null; - this.all_block_types = [ - "normal", "normal", "normal", "normal", "normal", - "normal", "normal", "normal", "normal", "normal" - ]; - } - onConnect(name) { - this.x = 0.0; - this.y = 0.0; - this.velocity_x = 0.0; - this.velocity_y = 0.0; - camera.x = 0.0; - camera.y = 0.0; - chatOpened = false; - chatMessages = []; - this.name = name; - this.color = "#5e6"; - blocks = []; - this.reset(); - } - register() { - document.addEventListener("keydown", (e) => { - let key = e.code; - if (chatOpened) { - if (key == "Backspace") { - chatTyping = chatTyping.slice(0, chatTyping.length - 1); - } - else if (key == "Enter") { - if (chatTyping == "") { - chatOpened = false; - return; - } - this.sendPacket(new MessagePacket(chatTyping)); - chatTyping = ""; - chatOpened = false; - } - else if (key == "Escape") { - chatOpened = false; - } - else if (e.key.length == 1) { - chatTyping += e.key; - e.preventDefault(); - return false; - } - } - else { - if (key == "KeyD") { - this.controls_x = 1; - } - else if (key == "KeyA") { - this.controls_x = -1; - } - else if (key == "Space") { - this.controls_jump = true; - e.preventDefault(); - return false; - } - else if (key == "KeyR") { - if (this.conn == null) { - this.forceTeleport(0, 1); - } - } - else if (key == "KeyT") { - chatOpened = true; - } - if (e.key == "0") - this.block_type = null; - if ("123456789".includes(e.key)) - this.block_type = this.all_block_types[parseInt(e.key) - 1]; - if (allowed_key_to_send.includes(key)) { - this.sendPacket(new KeyPacket(key, true)); - } - if (key == "Escape") { - this.closeConnection(); - } - } - if (key == "F3") { - debugMode = !debugMode; - e.preventDefault(); - return false; - } - }); - document.addEventListener("keyup", (e) => { - let key = e.code; - if ((key == "KeyD" && this.controls_x == 1) - || (key == "KeyA" && this.controls_x == -1)) { - this.controls_x = 0; - } - else if (key == "Space" && this.controls_jump) { - this.controls_jump = false; - } - if (allowed_key_to_send.includes(key)) { - this.sendPacket(new KeyPacket(key, false)); - } - }); - canvas.addEventListener("wheel", e => { - if (e.deltaY > 0) { - camera.size *= 0.5 * (e.deltaY / 114); - } - else { - camera.size *= 2 * (e.deltaY / -114); - } - e.preventDefault(); - return false; - }); - canvas.addEventListener("mousedown", e => { - let rect = canvas.getBoundingClientRect(); - let size = 16 * camera.size; - let x = Math.round((e.clientX - rect.x) / size - (width / size / 2) + camera.x); - let y = Math.round((height - (e.clientY - rect.y)) / size - (height / size / 2) + camera.y); - if (e.buttons == 2 && this.block_type != null) { - if (this.conn == null) { - placeBlock(new Block(x, y, "#555", true, this.block_type)); - } - this.sendPacket(new PlaceBlockPacket(x, y, this.block_type)); - } - else if (e.buttons == 1) { - if (this.conn == null) { - removeBlock(x, y); - } - this.sendPacket(new DestroyBlockPacket(x, y)); - } - }); - } - sendPacket(packet) { - if (this.conn != null) { - this.conn.send(packet); - } - } - closeConnection() { - if (this.conn != null) - this.conn.close(); - this.conn = null; - } - onPacket(packet) { - let packet_id = packet.getId(); - let packet_data = packet.getData(); - if (packet_id == "K") { - setServerError(packet_data[0]); - this.closeConnection(); - } - if (packet_id == "N") { - this.name = packet_data[0]; - } - if (packet_id == "C") { - this.color = packet_data[0]; - } - if (packet_id == "M") { - chatMessages.unshift(...packet_data); - } - if (packet_id == "R") { - this.velocity_x = parseFloat(packet_data[0]) - this.x + parseFloat(packet_data[2]); - this.velocity_y = parseFloat(packet_data[1]) - this.y + parseFloat(packet_data[3]); - } - if (packet_id == "P") { - let x = parseFloat(packet_data[0]); - let y = parseFloat(packet_data[1]); - this.x = x; - this.y = y; - } - if (packet_id == "V") { - let x = parseFloat(packet_data[0]); - let y = parseFloat(packet_data[1]); - this.velocity_x = x; - this.velocity_y = y; - } - if (packet_id == "S") { - let speed_type = packet_data[0]; - let speed = parseFloat(packet_data[1]); - if (speed_type == "W") { - this.walk_speed = speed; - } - else if (speed_type == "J") { - this.jump_speed = speed; - } - else if (speed_type == "G") { - this.gravity_speed = speed; - } - } - if (packet_id == "W") { - for (const data of packet_data) { - let type = data[0]; - let create = data[1] == "1"; - let params = data.slice(2).split(","); - if (type == "B") { - let x = parseFloat(params[0]); - let y = parseFloat(params[1]); - if (create) { - let collides = params[2] == "1"; - let type = params[3]; - let color = params[4]; - let block = getBlock(x, y); - if (block != null) { - block.x = x; - block.y = y; - block.color = color; - block.collides = collides; - block.type = type; - } - else { - placeBlock(new Block(x, y, color, collides, type)); - } - } - else { - removeBlock(x, y); - } - } - else if (type == "P") { - let name = params[0]; - if (create) { - let x = parseFloat(params[1]); - let y = parseFloat(params[2]); - let vel_x = parseFloat(params[3]); - let vel_y = parseFloat(params[4]); - let color = params[5]; - let player = getPlayer(name); - if (player != null) { - player.x = x; - player.y = y; - player.color = color; - player.velocity_x = vel_x; - player.velocity_y = vel_y; - } - else { - placeBlock(new Player(x, y, name, color, vel_x, vel_y)); - } - } - else { - removePlayer(name); - } - } - } - } - if (packet_id == "B") { - this.all_block_types = packet_data.slice(0, 9); - this.block_type = null; - } - } - tick() { - super.tick(false); - let vel_x = this.velocity_x; - let vel_y = this.velocity_y; - this.velocity_x += this.controls_x * this.walk_speed; - if (this.controls_jump && this.on_ground) { - this.velocity_y += this.jump_speed; - this.on_ground = false; - } - else { - this.velocity_y -= this.gravity_speed; - } - this.collide(); - ticksAlive++; - this.sendPacket(new VelocityPacket(this.velocity_x - vel_x, this.velocity_y - vel_y)); - this.sendPacket(new PositionPacket(this.x, this.y)); - } - render() { - super.render(); - camera.x = Math.round(lerp(camera.x, this.x, 0.075) * 1000) / 1000; - camera.y = Math.round(lerp(camera.y, this.y, 0.075) * 1000) / 1000; - } - renderText() { - super.renderText(); - if (this.block_type != null) { - ctx.fillStyle = "#76d"; - ctx.font = "15px monospace"; - ctx.fillText("selected: " + this.block_type, 0, 15); - } - if (debugMode) { - ctx.fillStyle = "#de7"; - ctx.font = "20px monospace"; - ctx.fillText("x: " + this.x, 0, 20); - ctx.fillText("y: " + this.y, 0, 40); - ctx.fillText("velocity_x: " + this.velocity_x, 0, 60); - ctx.fillText("velocity_y: " + this.velocity_y, 0, 80); - ctx.fillText("camera.x: " + camera.x, 0, 100); - ctx.fillText("camera.y: " + camera.y, 0, 120); - } - if (!chatOpened) { - ctx.fillStyle = "#22222288"; - ctx.fillRect(5, height - 35, width * 0.4, 30); - ctx.fillStyle = "#aaaaaa88"; - ctx.font = "15px monospace"; - ctx.fillText("Нажмите T для чата", 15, height - 15); - } - else { - ctx.fillStyle = "#22222288"; - ctx.fillRect(5, height - 35, width - 10, 30); - ctx.save(); - ctx.beginPath(); - ctx.moveTo(5, height - 35); - ctx.lineTo(width - 5, height - 35); - ctx.lineTo(width - 5, height - 5); - ctx.lineTo(5, height - 5); - ctx.lineTo(5, height - 35); - ctx.closePath(); - ctx.clip(); - ctx.font = "15px monospace"; - if (chatTyping.length == 0) { - ctx.fillStyle = "#aaaaaa88"; - ctx.fillText("Напишите сообщение...", 15, height - 15); - } - else { - ctx.fillStyle = "#ffffff"; - let text_width = ctx.measureText(chatTyping).width; - ctx.fillText(chatTyping, Math.min(10, width - text_width - 10), height - 15); - } - ctx.restore(); - } - if (chatMessages.length > 0) { - let draw_message = (message) => { - let lines = wrapText(ctx, message, message_width - 20); - let height = lines.length * 20 + 5 + 5; - let top = message_bottom - height; - ctx.fillStyle = "#22222288"; - ctx.fillRect(5, top, message_width, height); - let y = 5; - for (let line of lines) { - ctx.fillStyle = "#ffffff"; - ctx.fillText(line, 15, top + y + 15); - y += 5 + 20; - } - message_bottom -= height + 5; - }; - let message_width = width * 0.4; - let message_bottom = height - 35 - 5; - if (chatOpened) { - chatMessages.forEach(draw_message); - } - else { - draw_message(chatMessages[0]); - } - } - } -} -var ticksAlive = 0; -var debugMode = false; -var camera = { - x: 0.0, - y: 0.0, - size: 1.5 -}; -var chatOpened = false; -var chatMessages = []; -var chatTyping = ""; -var player = new MainPlayer(); -player.register(); -var blocks = []; -const allowed_key_to_send = [ - "KeyR", "KeyW", "KeyE", "KeyQ", "KeyS", - "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", - "Numpad6", "Numpad7", "Numpad8", "Numpad9", "Numpad0", - "ShiftLeft", "ControlLeft", "Enter", - "F1", "F2", "KeyZ", "KeyX", "KeyC" -]; -function connectServer(address, name) { - player.closeConnection(); - player.onConnect(name); - try { - let conn = new Connection(address, player.onPacket, (e) => { - player.conn = null; - setServerError(e == null ? "Connection closed due to error" : e); - resetWorld(); - }); - conn.send(new JoinPacket(name)); - } - catch (exception) { - setServerError(exception); - } -} -function resetWorld() { - player.onConnect("unnamed player"); - blocks = []; - blocks.push(new Block(-1, -1, "#555", true, "normal")); - blocks.push(new Block(0, -1, "#a67", true, "spawn")); - blocks.push(new Block(1, -1, "#555", true, "normal")); -} -function getBlock(x, y) { - let value = blocks.find(o => !(o instanceof Player) && o.x == x && o.y == y); - if (typeof value === "undefined") { - return null; - } - else { - return value; - } -} -function placeBlock(block) { - blocks.push(block); -} -function removeBlock(x, y) { - blocks = blocks.filter(o => o instanceof Player || o.x != x || o.y != y); -} -function getPlayer(name) { - let value = blocks.find(o => o instanceof Player && o.name == name); - if (typeof value === "undefined") { - return null; - } - else { - return value; - } -} -function removePlayer(name) { - blocks = blocks.filter(o => !(o instanceof Player) || o.name != name); -} -function render() { - ctx.fillStyle = "#333"; - ctx.fillRect(0, 0, width, height); - for (const block of blocks) - block.render(); - for (const block of blocks) - block.renderText(); - player.render(); - player.renderText(); -} -function tick() { - for (const block of blocks) - block.tick(); - player.tick(); -} -function renderTick() { - for (const block of blocks) - block.renderTick(); - player.renderTick(); -} -resetWorld();