stevenarella/src/main.rs

334 lines
10 KiB
Rust
Raw Normal View History

2016-03-16 14:25:35 -04:00
// Copyright 2016 Matthew Collins
2015-09-17 11:21:56 -04:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![recursion_limit="300"]
2016-03-19 12:32:13 -04:00
#![feature(const_fn)]
2016-03-26 10:24:26 -04:00
#![feature(plugin)]
// #![plugin(clippy)]
// #![allow(similar_names)]
// #![allow(new_without_default)]
// #![allow(many_single_char_names)]
// #![allow(if_not_else)]
// #![allow(float_cmp)]
// #![allow(single_char_pattern)]
// #![allow(too_many_arguments)]
// #![allow(cyclomatic_complexity)]
2016-03-25 09:15:35 -04:00
extern crate sdl2;
2016-03-19 20:29:35 -04:00
extern crate image;
extern crate time;
extern crate byteorder;
extern crate serde_json;
extern crate steven_openssl as openssl;
extern crate hyper;
extern crate flate2;
extern crate rand;
extern crate rustc_serialize;
extern crate cgmath;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
2016-03-22 07:47:02 -04:00
extern crate collision;
2016-03-19 20:29:35 -04:00
2016-03-18 18:24:30 -04:00
#[macro_use]
pub mod macros;
2016-03-23 17:07:49 -04:00
pub mod ecs;
2015-09-17 11:04:25 -04:00
pub mod protocol;
pub mod format;
pub mod nbt;
pub mod item;
pub mod gl;
pub mod types;
pub mod resources;
pub mod render;
2015-09-18 17:02:08 -04:00
pub mod ui;
2015-09-23 15:16:25 -04:00
pub mod screen;
2015-09-28 18:37:14 -04:00
#[macro_use]
pub mod console;
2016-03-18 18:24:30 -04:00
pub mod server;
pub mod world;
2016-03-19 12:32:13 -04:00
pub mod chunk_builder;
pub mod auth;
2016-03-24 11:39:57 -04:00
pub mod model;
2015-09-17 11:04:25 -04:00
2015-09-29 17:33:24 -04:00
use std::sync::{Arc, RwLock, Mutex};
2015-09-28 18:37:14 -04:00
use std::marker::PhantomData;
2016-03-20 08:04:02 -04:00
use std::thread;
use std::sync::mpsc;
2015-09-07 16:11:00 -04:00
2015-09-28 18:37:14 -04:00
const CL_BRAND: console::CVar<String> = console::CVar {
ty: PhantomData,
name: "cl_brand",
2015-10-07 14:36:59 -04:00
description: "cl_brand has the value of the clients current 'brand'. e.g. \"Steven\" or \
\"Vanilla\"",
2015-09-28 18:37:14 -04:00
mutable: false,
2015-10-01 15:07:27 -04:00
serializable: false,
2016-03-16 15:11:50 -04:00
default: &|| "Steven".to_owned(),
2015-09-28 18:37:14 -04:00
};
pub struct Game {
renderer: render::Renderer,
screen_sys: screen::ScreenSystem,
resource_manager: Arc<RwLock<resources::Manager>>,
2015-09-29 17:33:24 -04:00
console: Arc<Mutex<console::Console>>,
2015-10-01 15:07:27 -04:00
should_close: bool,
2016-03-18 18:24:30 -04:00
server: server::Server,
focused: bool,
2016-03-19 12:32:13 -04:00
chunk_builder: chunk_builder::ChunkBuilder,
2016-03-20 08:04:02 -04:00
connect_reply: Option<mpsc::Receiver<Result<server::Server, protocol::Error>>>,
}
impl Game {
pub fn connect_to(&mut self, address: &str) {
let (tx, rx) = mpsc::channel();
self.connect_reply = Some(rx);
let address = address.to_owned();
let resources = self.resource_manager.clone();
2016-03-21 06:55:31 -04:00
let console = self.console.clone();
2016-03-20 08:04:02 -04:00
thread::spawn(move || {
2016-03-21 06:55:31 -04:00
tx.send(server::Server::connect(resources, console, &address)).unwrap();
2016-03-20 08:04:02 -04:00
});
}
2016-03-21 08:56:38 -04:00
pub fn tick(&mut self, delta: f64) {
if !self.server.is_connected() {
self.server.yaw += 0.005 * delta;
if self.server.yaw > ::std::f64::consts::PI * 2.0 {
self.server.yaw = 0.0;
2016-03-21 08:56:38 -04:00
}
}
2016-03-20 08:04:02 -04:00
let mut clear_reply = false;
if let Some(ref recv) = self.connect_reply {
if let Ok(server) = recv.try_recv() {
clear_reply = true;
match server {
Ok(val) => {
self.screen_sys.pop_screen();
self.focused = true;
2016-03-20 08:04:02 -04:00
self.server = val;
},
Err(err) => {
let msg = match err {
protocol::Error::Disconnect(val) => val,
err => {
let mut msg = format::TextComponent::new(&format!("{}", err));
msg.modifier.color = Some(format::Color::Red);
format::Component::Text(msg)
},
};
self.screen_sys.replace_screen(Box::new(screen::ServerList::new(
Some(msg)
)));
}
}
}
}
if clear_reply {
self.connect_reply = None;
}
}
2015-09-28 18:37:14 -04:00
}
2015-09-07 16:11:00 -04:00
fn main() {
2015-09-29 17:33:24 -04:00
let con = Arc::new(Mutex::new(console::Console::new()));
2015-09-29 18:24:58 -04:00
{
let mut con = con.lock().unwrap();
con.register(CL_BRAND);
auth::register_vars(&mut con);
2015-09-29 18:24:58 -04:00
con.load_config();
con.save_config();
}
2015-10-01 15:07:27 -04:00
2015-09-29 17:33:24 -04:00
let proxy = console::ConsoleProxy::new(con.clone());
2015-10-01 15:07:27 -04:00
2015-09-29 17:33:24 -04:00
log::set_logger(|max_log_level| {
max_log_level.set(log::LogLevelFilter::Trace);
Box::new(proxy)
2016-03-18 18:24:30 -04:00
}).unwrap();
2015-09-29 17:33:24 -04:00
info!("Starting steven");
2015-09-28 18:37:14 -04:00
2015-09-17 11:04:25 -04:00
let resource_manager = Arc::new(RwLock::new(resources::Manager::new()));
2015-10-07 14:36:59 -04:00
{
resource_manager.write().unwrap().tick();
}
2015-09-17 11:04:25 -04:00
2016-03-25 09:15:35 -04:00
let sdl = sdl2::init().unwrap();
let sdl_video = sdl.video().unwrap();
sdl_video.gl_set_swap_interval(1);
let window = sdl2::video::WindowBuilder::new(&sdl_video, "Steven", 854, 480)
.opengl()
.resizable()
.build()
.expect("Could not create sdl window.");
let gl_attr = sdl_video.gl_attr();
gl_attr.set_stencil_size(0);
gl_attr.set_depth_size(24);
gl_attr.set_context_major_version(3);
gl_attr.set_context_minor_version(2);
gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
let gl_context = window.gl_create_context().unwrap();
window.gl_make_current(&gl_context).expect("Could not set current context.");
2015-09-07 16:11:00 -04:00
2016-03-25 09:15:35 -04:00
gl::init(&sdl_video);
2015-09-07 16:11:00 -04:00
2015-09-28 18:37:14 -04:00
let renderer = render::Renderer::new(resource_manager.clone());
2015-09-18 17:02:08 -04:00
let mut ui_container = ui::Container::new();
2015-09-17 11:04:25 -04:00
let mut last_frame = time::now();
let frame_time = (time::Duration::seconds(1).num_nanoseconds().unwrap() as f64) / 60.0;
2015-09-23 15:16:25 -04:00
let mut screen_sys = screen::ScreenSystem::new();
screen_sys.add_screen(Box::new(screen::Login::new(con.clone())));
2015-09-19 14:08:28 -04:00
2016-03-19 12:32:13 -04:00
let textures = renderer.get_textures();
2015-09-28 18:37:14 -04:00
let mut game = Game {
2016-03-21 06:55:31 -04:00
server: server::Server::dummy_server(resource_manager.clone(), con.clone()),
focused: false,
2015-09-28 18:37:14 -04:00
renderer: renderer,
screen_sys: screen_sys,
2016-03-24 11:39:57 -04:00
resource_manager: resource_manager.clone(),
2015-09-28 18:37:14 -04:00
console: con,
2015-10-01 15:07:27 -04:00
should_close: false,
2016-03-24 11:39:57 -04:00
chunk_builder: chunk_builder::ChunkBuilder::new(resource_manager, textures),
2016-03-20 08:04:02 -04:00
connect_reply: None,
2015-09-28 18:37:14 -04:00
};
2016-03-25 09:15:35 -04:00
let mut events = sdl.event_pump().unwrap();
2015-10-01 15:07:27 -04:00
while !game.should_close {
2015-10-07 14:36:59 -04:00
{
game.resource_manager.write().unwrap().tick();
}
2015-10-01 15:07:27 -04:00
2015-09-17 11:04:25 -04:00
let now = time::now();
let diff = now - last_frame;
last_frame = now;
let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
2016-03-25 09:15:35 -04:00
let (width, height) = window.size();
2015-09-17 11:04:25 -04:00
2016-03-21 08:56:38 -04:00
game.tick(delta);
2016-03-21 10:05:13 -04:00
game.server.tick(&mut game.renderer, delta);
2016-03-19 13:34:12 -04:00
2016-03-24 17:47:11 -04:00
game.renderer.update_camera(width, height);
game.server.world.compute_render_list(&mut game.renderer);
game.chunk_builder.tick(&mut game.server.world, &mut game.renderer, delta);
2016-03-19 12:32:13 -04:00
2015-09-28 18:37:14 -04:00
game.screen_sys.tick(delta, &mut game.renderer, &mut ui_container);
2015-10-07 14:36:59 -04:00
game.console
.lock()
.unwrap()
.tick(&mut ui_container, &mut game.renderer, delta, width as f64);
2015-09-28 18:37:14 -04:00
ui_container.tick(&mut game.renderer, delta, width as f64, height as f64);
2016-03-24 17:13:24 -04:00
game.renderer.tick(&mut game.server.world, delta, width, height);
2015-10-01 15:07:27 -04:00
2016-03-25 09:15:35 -04:00
window.gl_swap_window();
2015-09-07 16:11:00 -04:00
2016-03-25 09:15:35 -04:00
for event in events.poll_iter() {
2015-10-01 15:07:27 -04:00
handle_window_event(&window, &mut game, &mut ui_container, event)
2015-09-07 16:11:00 -04:00
}
}
}
2016-03-25 09:15:35 -04:00
fn handle_window_event(window: &sdl2::video::Window,
2015-10-07 14:36:59 -04:00
game: &mut Game,
ui_container: &mut ui::Container,
2016-03-25 09:15:35 -04:00
event: sdl2::event::Event) {
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::mouse::Mouse;
use std::f64::consts::PI;
2016-03-25 09:15:35 -04:00
let mouse = window.subsystem().sdl().mouse();
2015-09-07 16:11:00 -04:00
match event {
2016-03-25 09:15:35 -04:00
Event::Quit{..} => game.should_close = true,
2015-10-01 15:07:27 -04:00
2016-03-25 09:15:35 -04:00
Event::MouseMotion{x, y, xrel, yrel, ..} => {
let (width, height) = window.size();
if game.focused {
2016-03-25 09:15:35 -04:00
if !mouse.relative_mouse_mode() {
mouse.set_relative_mouse_mode(true);
}
let s = 2000.0 + 0.01;
2016-03-25 09:15:35 -04:00
let (rx, ry) = (xrel as f64 / s, yrel as f64 / s);
game.server.yaw -= rx;
game.server.pitch -= ry;
if game.server.pitch < (PI/2.0) + 0.01 {
game.server.pitch = (PI/2.0) + 0.01;
}
if game.server.pitch > (PI/2.0)*3.0 - 0.01 {
game.server.pitch = (PI/2.0)*3.0 - 0.01;
}
} else {
ui_container.hover_at(game, x as f64, y as f64, width as f64, height as f64);
}
2015-10-07 14:36:59 -04:00
}
2016-03-25 09:15:35 -04:00
Event::MouseButtonUp{mouse_btn: Mouse::Left, x, y, ..} => {
let (width, height) = window.size();
2015-10-01 15:07:27 -04:00
if game.server.is_connected() && !game.focused {
game.focused = true;
2016-03-25 09:15:35 -04:00
mouse.set_relative_mouse_mode(true);
mouse.warp_mouse_in_window(&window, (width/2) as i32, (height/2) as i32);
return;
}
if !game.focused {
ui_container.click_at(game, x as f64, y as f64, width as f64, height as f64);
}
2015-10-07 14:36:59 -04:00
}
2016-03-25 09:15:35 -04:00
Event::MouseWheel{x, y, ..} => {
2015-10-01 15:07:27 -04:00
game.screen_sys.on_scroll(x as f64, y as f64);
2015-10-07 14:36:59 -04:00
}
2016-03-25 09:15:35 -04:00
Event::KeyUp{keycode: Some(Keycode::Escape), ..} => {
if game.focused {
2016-03-25 09:15:35 -04:00
mouse.set_relative_mouse_mode(false);
game.focused = false;
}
}
2016-03-25 09:15:35 -04:00
Event::KeyDown{keycode: Some(Keycode::Backquote), ..} => {
2015-10-06 19:10:59 -04:00
game.console.lock().unwrap().toggle();
2015-10-07 14:36:59 -04:00
}
2016-03-25 09:15:35 -04:00
Event::KeyDown{keycode: Some(key), ..} => {
if game.focused {
2016-03-25 09:15:35 -04:00
game.server.key_press(true, key);
} else {
2016-03-25 09:15:35 -04:00
ui_container.key_press(game, key, true);
}
}
2016-03-25 09:15:35 -04:00
Event::KeyUp{keycode: Some(key), ..} => {
if game.focused {
game.server.key_press(false, key);
} else {
ui_container.key_press(game, key, false);
}
}
Event::TextInput{text, ..} => {
if !game.focused {
2016-03-25 09:15:35 -04:00
for c in text.chars() {
ui_container.key_type(game, c);
}
}
2015-10-07 14:36:59 -04:00
}
_ => (),
2015-09-07 16:11:00 -04:00
}
}