Make lowest line of Splash image frames transparent to work around scaling issues
The Splash image is scaled. Sometimes, the lowest line is repeated on the top, which caused some weird lines to appear above big splashes (e.g. piano).
This has been done fully automated with a script. Only the alpha channel was changed. The color information is preserved.
use std::{
fs::{File, OpenOptions},
io::{Error, ErrorKind, Read, Result, Write},
sync::mpsc,
thread,
};
use crate::{
handlers::{IoResult, IoTask},
server::database::Database,
};
use log::*;
use mio::{Evented, Poll, PollOpt};
use mio_extras::channel;
pub type RequestId = u32;
pub struct IoThread {
core_tx: mpsc::Sender<(RequestId, IoTask)>,
core_rx: channel::Receiver<(RequestId, IoResult)>,
}
impl IoThread {
pub fn new() -> Self {
let (core_tx, io_rx) = mpsc::channel();
let (io_tx, core_rx) = channel::channel();
let mut db = Database::new();
db.connect("localhost");
thread::spawn(move || {
while let Ok((request_id, task)) = io_rx.recv() {
let response = match task {
IoTask::CheckRegistered { nick } => match db.is_registered(&nick) {
Ok(is_registered) => IoResult::AccountRegistered(is_registered),
Err(e) => {
warn!("Unable to check account's existence: {}", e);
IoResult::AccountRegistered(false)
}
},
IoTask::GetAccount {
nick,
protocol,
password_hash,
client_salt,
server_salt,
} => {
match db.get_account(
&nick,
protocol,
&password_hash,
&client_salt,
&server_salt,
) {
Ok(account) => IoResult::Account(account),
Err(e) => {
warn!("Unable to get account data: {}", e);
IoResult::Account(None)
}
}
}
IoTask::GetReplay { id } => {
let result = match db.get_replay_name(id) {
Ok(Some(filename)) => {
let filename = format!(
"checked/{}",
if filename.starts_with("replays/") {
&filename[8..]
} else {
&filename
}
);
match load_file(&filename) {
Ok(contents) => Some(unimplemented!()),
Err(e) => {
warn!(
"Error while writing the room config file \"{}\": {}",
filename, e
);
None
}
}
}
Ok(None) => None,
Err(e) => {
warn!("Unable to get replay name: {}", e);
None
}
};
IoResult::Replay(result)
}
IoTask::SaveRoom {
room_id,
filename,
contents,
} => {
let result = match save_file(&filename, &contents) {
Ok(()) => true,
Err(e) => {
warn!(
"Error while writing the room config file \"{}\": {}",
filename, e
);
false
}
};
IoResult::SaveRoom(room_id, result)
}
IoTask::LoadRoom { room_id, filename } => {
let result = match load_file(&filename) {
Ok(contents) => Some(contents),
Err(e) => {
warn!(
"Error while writing the room config file \"{}\": {}",
filename, e
);
None
}
};
IoResult::LoadRoom(room_id, result)
}
};
io_tx.send((request_id, response));
}
});
Self { core_rx, core_tx }
}
pub fn send(&self, request_id: RequestId, task: IoTask) {
self.core_tx.send((request_id, task)).unwrap();
}
pub fn try_recv(&self) -> Option<(RequestId, IoResult)> {
match self.core_rx.try_recv() {
Ok(result) => Some(result),
Err(mpsc::TryRecvError::Empty) => None,
Err(mpsc::TryRecvError::Disconnected) => unreachable!(),
}
}
pub fn register_rx(&self, poll: &mio::Poll, token: mio::Token) -> Result<()> {
self.core_rx
.register(poll, token, mio::Ready::readable(), PollOpt::edge())
}
}
fn save_file(filename: &str, contents: &str) -> Result<()> {
let mut writer = OpenOptions::new().create(true).write(true).open(filename)?;
writer.write_all(contents.as_bytes())
}
fn load_file(filename: &str) -> Result<String> {
let mut reader = File::open(filename)?;
let mut result = String::new();
reader.read_to_string(&mut result)?;
Ok(result)
}