Merge branch 'master' of https://github.com/teeworlds/teeworlds into feature-complexbinds
3
.gitignore
vendored
|
@ -2,6 +2,8 @@
|
|||
/.bam
|
||||
/config.lua
|
||||
/build
|
||||
/other/*/lib
|
||||
/other/*/include
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
@ -9,3 +11,4 @@ scripts/work/
|
|||
/SDL.dll
|
||||
/freetype.dll
|
||||
/autoexec.cfg
|
||||
_test.exe
|
||||
|
|
2
.gitmodules
vendored
|
@ -1,6 +1,8 @@
|
|||
[submodule "datasrc/languages"]
|
||||
path = datasrc/languages
|
||||
url = git://github.com/teeworlds/teeworlds-translation.git
|
||||
branch = master
|
||||
[submodule "datasrc/maps"]
|
||||
path = datasrc/maps
|
||||
url = git://github.com/teeworlds/teeworlds-maps.git
|
||||
branch = master
|
||||
|
|
|
@ -17,10 +17,11 @@ class SoundSet(Struct):
|
|||
self.sounds.Add(Sound(name))
|
||||
|
||||
class Image(Struct):
|
||||
def __init__(self, name="", filename=""):
|
||||
def __init__(self, name="", filename="", linear_mapping=0):
|
||||
Struct.__init__(self, "CDataImage")
|
||||
self.name = String(name)
|
||||
self.filename = String(filename)
|
||||
self.flag = Int(linear_mapping)
|
||||
self.id = TextureHandle()
|
||||
|
||||
class SpriteSet(Struct):
|
||||
|
@ -233,16 +234,20 @@ container.sounds.Add(SoundSet("menu", ["audio/music_menu.wv"]))
|
|||
image_null = Image("null", "")
|
||||
image_particles = Image("particles", "particles.png")
|
||||
image_game = Image("game", "game.png")
|
||||
image_browseicons = Image("browseicons", "ui/icons/browse.png")
|
||||
image_browseicons = Image("browseicons", "ui/icons/browse.png", 1)
|
||||
image_emoticons = Image("emoticons", "emoticons.png")
|
||||
image_demobuttons = Image("demobuttons", "ui/demo_buttons.png")
|
||||
image_fileicons = Image("fileicons", "ui/file_icons.png")
|
||||
image_guibuttons = Image("guibuttons", "ui/gui_buttons.png")
|
||||
image_guiicons = Image("guiicons", "ui/gui_icons.png")
|
||||
image_menuicons = Image("menuicons", "ui/icons/menu.png")
|
||||
image_toolicons = Image("toolicons", "ui/icons/tools.png")
|
||||
image_friendicons = Image("friendicons", "ui/icons/friend.png")
|
||||
image_infoicons = Image("infoicons", "ui/icons/info.png")
|
||||
image_demobuttons = Image("demobuttons", "ui/demo_buttons.png", 1)
|
||||
image_fileicons = Image("fileicons", "ui/file_icons.png", 1)
|
||||
image_guibuttons = Image("guibuttons", "ui/gui_buttons.png", 1)
|
||||
image_guiicons = Image("guiicons", "ui/gui_icons.png", 1)
|
||||
image_menuicons = Image("menuicons", "ui/icons/menu.png", 1)
|
||||
image_toolicons = Image("toolicons", "ui/icons/tools.png", 1)
|
||||
image_arrowicons = Image("arrowicons", "ui/icons/arrows.png", 1)
|
||||
image_friendicons = Image("friendicons", "ui/icons/friend.png", 1)
|
||||
image_infoicons = Image("infoicons", "ui/icons/info.png", 1)
|
||||
image_levelicons = Image("levelicons", "ui/icons/level.png", 1)
|
||||
image_sidebaricons = Image("sidebaricons", "ui/icons/sidebar.png", 1)
|
||||
image_chatwhisper = Image("chatwhisper", "ui/icons/chat_whisper.png", 1)
|
||||
|
||||
container.images.Add(image_null)
|
||||
container.images.Add(image_game)
|
||||
|
@ -261,8 +266,12 @@ container.images.Add(image_guiicons)
|
|||
container.images.Add(Image("no_skinpart", "ui/no_skinpart.png"))
|
||||
container.images.Add(image_menuicons)
|
||||
container.images.Add(image_toolicons)
|
||||
container.images.Add(image_arrowicons)
|
||||
container.images.Add(image_friendicons)
|
||||
container.images.Add(image_infoicons)
|
||||
container.images.Add(image_levelicons)
|
||||
container.images.Add(image_sidebaricons)
|
||||
container.images.Add(image_chatwhisper)
|
||||
|
||||
container.pickups.Add(Pickup("health"))
|
||||
container.pickups.Add(Pickup("armor"))
|
||||
|
@ -287,8 +296,11 @@ set_guibuttons = SpriteSet("guibuttons", image_guibuttons, 12, 4)
|
|||
set_guiicons = SpriteSet("guiicons", image_guiicons, 8, 2)
|
||||
set_menuicons = SpriteSet("menuicons", image_menuicons, 2, 2)
|
||||
set_toolicons = SpriteSet("toolicons", image_toolicons, 4, 2)
|
||||
set_arrowicons = SpriteSet("arrowicons", image_arrowicons, 4, 3)
|
||||
set_friendicons = SpriteSet("friendicons", image_friendicons, 2, 2)
|
||||
set_infoicons = SpriteSet("infoicons", image_infoicons, 1, 2)
|
||||
set_levelicons = SpriteSet("levelicons", image_levelicons, 4, 4)
|
||||
set_sidebaricons = SpriteSet("sidebaricons", image_sidebaricons, 4, 2)
|
||||
|
||||
container.spritesets.Add(set_particles)
|
||||
container.spritesets.Add(set_game)
|
||||
|
@ -306,8 +318,12 @@ container.spritesets.Add(set_guibuttons)
|
|||
container.spritesets.Add(set_guiicons)
|
||||
container.spritesets.Add(set_menuicons)
|
||||
container.spritesets.Add(set_toolicons)
|
||||
container.spritesets.Add(set_arrowicons)
|
||||
container.spritesets.Add(set_friendicons)
|
||||
container.spritesets.Add(set_infoicons)
|
||||
container.spritesets.Add(set_levelicons)
|
||||
container.spritesets.Add(set_sidebaricons)
|
||||
|
||||
|
||||
container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1))
|
||||
container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1))
|
||||
|
@ -387,6 +403,11 @@ container.sprites.Add(Sprite("pickup_ninja", set_game, 2,10,8,2))
|
|||
container.sprites.Add(Sprite("flag_blue", set_game, 12,8,4,8))
|
||||
container.sprites.Add(Sprite("flag_red", set_game, 16,8,4,8))
|
||||
|
||||
container.sprites.Add(Sprite("ninja_bar_full_left", set_game, 21,4,1,2))
|
||||
container.sprites.Add(Sprite("ninja_bar_full", set_game, 22,4,1,2))
|
||||
container.sprites.Add(Sprite("ninja_bar_empty", set_game, 23,4,1,2))
|
||||
container.sprites.Add(Sprite("ninja_bar_empty_right", set_game, 24,4,1,2))
|
||||
|
||||
container.sprites.Add(Sprite("tee_body_outline", set_tee_body, 0,0,1,1))
|
||||
container.sprites.Add(Sprite("tee_body", set_tee_body, 1,0,1,1))
|
||||
container.sprites.Add(Sprite("tee_body_shadow", set_tee_body, 0,1,1,1))
|
||||
|
@ -472,6 +493,19 @@ container.sprites.Add(Sprite("tool_edit_b", set_toolicons, 2,1,1,1))
|
|||
container.sprites.Add(Sprite("tool_x_a", set_toolicons, 3,0,1,1))
|
||||
container.sprites.Add(Sprite("tool_x_b", set_toolicons, 3,1,1,1))
|
||||
|
||||
container.sprites.Add(Sprite("arrow_left_a", set_arrowicons, 0,0,1,1))
|
||||
container.sprites.Add(Sprite("arrow_left_b", set_arrowicons, 0,1,1,1))
|
||||
container.sprites.Add(Sprite("arrow_left_c", set_arrowicons, 0,2,1,1))
|
||||
container.sprites.Add(Sprite("arrow_up_a", set_arrowicons, 1,0,1,1))
|
||||
container.sprites.Add(Sprite("arrow_up_b", set_arrowicons, 1,1,1,1))
|
||||
container.sprites.Add(Sprite("arrow_up_c", set_arrowicons, 1,2,1,1))
|
||||
container.sprites.Add(Sprite("arrow_right_a", set_arrowicons, 2,0,1,1))
|
||||
container.sprites.Add(Sprite("arrow_right_b", set_arrowicons, 2,1,1,1))
|
||||
container.sprites.Add(Sprite("arrow_right_c", set_arrowicons, 2,2,1,1))
|
||||
container.sprites.Add(Sprite("arrow_down_a", set_arrowicons, 3,0,1,1))
|
||||
container.sprites.Add(Sprite("arrow_down_b", set_arrowicons, 3,1,1,1))
|
||||
container.sprites.Add(Sprite("arrow_down_c", set_arrowicons, 3,2,1,1))
|
||||
|
||||
container.sprites.Add(Sprite("friend_plus_a", set_friendicons, 0,0,1,1))
|
||||
container.sprites.Add(Sprite("friend_plus_b", set_friendicons, 0,1,1,1))
|
||||
container.sprites.Add(Sprite("friend_x_a", set_friendicons, 1,0,1,1))
|
||||
|
@ -480,6 +514,24 @@ container.sprites.Add(Sprite("friend_x_b", set_friendicons, 1,1,1,1))
|
|||
container.sprites.Add(Sprite("info_a", set_infoicons, 0,0,1,1))
|
||||
container.sprites.Add(Sprite("info_b", set_infoicons, 0,1,1,1))
|
||||
|
||||
container.sprites.Add(Sprite("level_a_on", set_levelicons, 0,0,1,1))
|
||||
container.sprites.Add(Sprite("level_a_a", set_levelicons, 0,1,1,1))
|
||||
container.sprites.Add(Sprite("level_a_b", set_levelicons, 0,2,1,1))
|
||||
container.sprites.Add(Sprite("level_b_on", set_levelicons, 1,0,1,1))
|
||||
container.sprites.Add(Sprite("level_b_a", set_levelicons, 1,1,1,1))
|
||||
container.sprites.Add(Sprite("level_b_b", set_levelicons, 1,2,1,1))
|
||||
container.sprites.Add(Sprite("level_c_on", set_levelicons, 2,0,1,1))
|
||||
container.sprites.Add(Sprite("level_c_a", set_levelicons, 2,1,1,1))
|
||||
container.sprites.Add(Sprite("level_c_b", set_levelicons, 2,2,1,1))
|
||||
|
||||
container.sprites.Add(Sprite("sidebar_refresh_a", set_sidebaricons, 0,0,1,1))
|
||||
container.sprites.Add(Sprite("sidebar_refresh_b", set_sidebaricons, 0,1,1,1))
|
||||
container.sprites.Add(Sprite("sidebar_friend_a", set_sidebaricons, 1,0,1,1))
|
||||
container.sprites.Add(Sprite("sidebar_friend_b", set_sidebaricons, 1,1,1,1))
|
||||
container.sprites.Add(Sprite("sidebar_filter_a", set_sidebaricons, 2,0,1,1))
|
||||
container.sprites.Add(Sprite("sidebar_filter_b", set_sidebaricons, 2,1,1,1))
|
||||
container.sprites.Add(Sprite("sidebar_info_a", set_sidebaricons, 3,0,1,1))
|
||||
container.sprites.Add(Sprite("sidebar_info_b", set_sidebaricons, 3,1,1,1))
|
||||
|
||||
anim = Animation("base")
|
||||
anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0))
|
||||
|
@ -552,7 +604,7 @@ weapon.damage.Set(1)
|
|||
weapon.ammoregentime.Set(500)
|
||||
weapon.visual_size.Set(64)
|
||||
weapon.offsetx.Set(32)
|
||||
weapon.offsety.Set(4)
|
||||
weapon.offsety.Set(-4)
|
||||
weapon.muzzleoffsetx.Set(50)
|
||||
weapon.muzzleoffsety.Set(6)
|
||||
container.weapons.gun.base.Set(weapon)
|
||||
|
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
datasrc/game.png
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 137 KiB |
|
@ -1 +1 @@
|
|||
Subproject commit ad1818b3f3fd16edf1388976d697ff03b66d8c58
|
||||
Subproject commit 5111dfa5ef0639045606bcda485dc32f7d24df49
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 225 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 155 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 13 KiB |
|
@ -1 +1 @@
|
|||
Subproject commit 250e1e5d5cb2bf2ba4661b924a9bd79a352aa391
|
||||
Subproject commit 31b9e3cd594396fdb482d228ed61bc454baee622
|
|
@ -6,7 +6,7 @@ Emoticons = Enum("EMOTICON", ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT",
|
|||
Votes = Enum("VOTE", ["UNKNOWN", "START_OP", "START_KICK", "START_SPEC", "END_ABORT", "END_PASS", "END_FAIL"])
|
||||
ChatModes = Enum("CHAT", ["NONE", "ALL", "TEAM", "WHISPER"])
|
||||
|
||||
PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING"])
|
||||
PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING", "BOT"])
|
||||
GameFlags = Flags("GAMEFLAG", ["TEAMS", "FLAGS", "SURVIVAL"])
|
||||
GameStateFlags = Flags("GAMESTATEFLAG", ["WARMUP", "SUDDENDEATH", "ROUNDOVER", "GAMEOVER", "PAUSED", "STARTCOUNTDOWN"])
|
||||
CoreEventFlags = Flags("COREEVENTFLAG", ["GROUND_JUMP", "AIR_JUMP", "HOOK_ATTACH_PLAYER", "HOOK_ATTACH_GROUND", "HOOK_HIT_NOHOOK"])
|
||||
|
@ -246,6 +246,7 @@ Messages = [
|
|||
NetMessage("Sv_Chat", [
|
||||
NetIntRange("m_Mode", 0, 'NUM_CHATS-1'),
|
||||
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
|
||||
NetIntRange("m_TargetID", -1, 'MAX_CLIENTS-1'),
|
||||
NetStringStrict("m_pMessage"),
|
||||
]),
|
||||
|
||||
|
@ -322,6 +323,7 @@ Messages = [
|
|||
NetArray(NetStringStrict("m_apSkinPartNames"), 6),
|
||||
NetArray(NetBool("m_aUseCustomColors"), 6),
|
||||
NetArray(NetIntAny("m_aSkinPartColors"), 6),
|
||||
NetBool("m_Silent"),
|
||||
]),
|
||||
|
||||
NetMessage("Sv_GameInfo", [
|
||||
|
@ -337,6 +339,7 @@ Messages = [
|
|||
NetMessage("Sv_ClientDrop", [
|
||||
NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'),
|
||||
NetStringStrict("m_pReason"),
|
||||
NetBool("m_Silent"),
|
||||
]),
|
||||
|
||||
NetMessage("Sv_GameMsg", []),
|
||||
|
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
datasrc/ui/icons/arrows.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
datasrc/ui/icons/chat_whisper.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
datasrc/ui/icons/level.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
datasrc/ui/icons/sidebar.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
datasrc/ui/themes/heavens.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
datasrc/ui/themes/heavens_day.map
Normal file
BIN
datasrc/ui/themes/heavens_night.map
Normal file
BIN
datasrc/ui/themes/jungle.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
datasrc/ui/themes/none.png
Normal file
After Width: | Height: | Size: 989 B |
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 2007-2016 Magnus Auvinen
|
||||
Copyright (C) 2007-2018 Magnus Auvinen
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -21,6 +21,11 @@ freely, subject to the following restrictions:
|
|||
All content under 'data' and 'datasrc' except the font (which has its own license) is
|
||||
released under CC-BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/).
|
||||
|
||||
Authors: android272, Chi11y (chi1), Crises, Daniel, Echchouik, Fisico,
|
||||
Landil, Lappi, LordSk, maikka, matricks, Pocram, red_com,
|
||||
serpis, SkizZ, somerunce, Sonix, Stephanator, teetow, Ubu,
|
||||
Zatline
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
IMPORTANT NOTE! The source under src/engine/external are stripped
|
||||
|
|
|
@ -88,6 +88,12 @@ def clean():
|
|||
package = "%s-%s-%s" %(name, version, platform)
|
||||
package_dir = package
|
||||
|
||||
source_package_dir = "build/"
|
||||
if platform == 'win32' or platform == 'linux_x86':
|
||||
source_package_dir += "x86/release/"
|
||||
else:
|
||||
source_package_dir += "x86_64/release/"
|
||||
|
||||
print("cleaning target")
|
||||
shutil.rmtree(package_dir, True)
|
||||
os.mkdir(package_dir)
|
||||
|
@ -118,18 +124,17 @@ shutil.copy("license.txt", package_dir)
|
|||
shutil.copy("storage.cfg", package_dir)
|
||||
|
||||
if include_data and not use_bundle:
|
||||
os.mkdir(os.path.join(package_dir, "data"))
|
||||
copydir("data", package_dir)
|
||||
shutil.copytree(source_package_dir+"data", package_dir+"/data")
|
||||
copyfiles(languages_dir, package_dir+"/data/languages")
|
||||
copyfiles(maps_dir, package_dir+"/data/maps")
|
||||
if platform[:3] == "win":
|
||||
shutil.copy("other/config_directory.bat", package_dir)
|
||||
shutil.copy("SDL.dll", package_dir)
|
||||
shutil.copy("freetype.dll", package_dir)
|
||||
shutil.copy(source_package_dir+"SDL2.dll", package_dir)
|
||||
shutil.copy(source_package_dir+"freetype.dll", package_dir)
|
||||
|
||||
if include_exe and not use_bundle:
|
||||
shutil.copy(name+exe_ext, package_dir)
|
||||
shutil.copy(name+"_srv"+exe_ext, package_dir)
|
||||
shutil.copy(source_package_dir+name+exe_ext, package_dir)
|
||||
shutil.copy(source_package_dir+name+"_srv"+exe_ext, package_dir)
|
||||
|
||||
if include_src:
|
||||
for p in ["src", "scripts", "datasrc", "other", "objs"]:
|
||||
|
|
|
@ -1,160 +1,172 @@
|
|||
#!/bin/env python3
|
||||
# coding: utf-8
|
||||
from socket import *
|
||||
import struct
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
import random
|
||||
|
||||
NUM_MASTERSERVERS = 4
|
||||
MASTERSERVER_PORT = 8300
|
||||
MASTERSERVER_PORT = 8283
|
||||
|
||||
TIMEOUT = 2
|
||||
|
||||
SERVERTYPE_NORMAL = 0
|
||||
SERVERTYPE_LEGACY = 1
|
||||
# src/mastersrv/mastersrv.h
|
||||
PACKET_GETLIST = b"\xff\xff\xff\xffreq2"
|
||||
PACKET_LIST = b"\xff\xff\xff\xfflis2"
|
||||
|
||||
PACKET_GETLIST = "\x20\x00\x00\x00\x00\x00\xff\xff\xff\xffreqt"
|
||||
PACKET_GETLIST2 = "\x20\x00\x00\x00\x00\x00\xff\xff\xff\xffreq2"
|
||||
PACKET_GETINFO = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgief"
|
||||
PACKET_GETINFO2 = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgie2" + "\x00"
|
||||
PACKET_GETINFO3 = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgie3" + "\x00"
|
||||
PACKET_GETINFO = b"\xff\xff\xff\xffgie3"
|
||||
PACKET_INFO = b"\xff\xff\xff\xffinf3"
|
||||
|
||||
# see CNetBase::SendControlMsgWithToken
|
||||
def pack_control_msg_with_token(token_srv,token_cl):
|
||||
NET_PACKETFLAG_CONTROL = 1
|
||||
NET_CTRLMSG_TOKEN = 5
|
||||
NET_TOKENREQUEST_DATASIZE = 512
|
||||
b = [0]*(4 + 3 + NET_TOKENREQUEST_DATASIZE)
|
||||
# Header
|
||||
b[0] = (token_srv >> 24) & 0xff
|
||||
b[1] = (token_srv >> 16) & 0xff
|
||||
b[2] = (token_srv >> 8) & 0xff
|
||||
b[3] = (token_srv) & 0xff
|
||||
b[4] = (NET_PACKETFLAG_CONTROL<<2)&0xfc
|
||||
# Data
|
||||
b[7] = NET_CTRLMSG_TOKEN
|
||||
b[8] = (token_cl >> 24) & 0xff
|
||||
b[9] = (token_cl >> 16) & 0xff
|
||||
b[10] = (token_cl >> 8) & 0xff
|
||||
b[11] = (token_cl) & 0xff
|
||||
return bytes(b)
|
||||
|
||||
def unpack_control_msg_with_token(msg):
|
||||
b = list(msg)
|
||||
token_cl = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + (b[3])
|
||||
token_srv = (b[8] << 24) + (b[9] << 16) + (b[10] << 8) + (b[11])
|
||||
return token_cl,token_srv
|
||||
|
||||
# CNetBase::SendPacketConnless
|
||||
def header_connless(token_srv, token_cl):
|
||||
NET_PACKETFLAG_CONNLESS = 8
|
||||
NET_PACKETVERSION = 1
|
||||
b = [0]*9
|
||||
b[0] = (token_srv >> 24) & 0xff
|
||||
b[1] = (token_srv >> 16) & 0xff
|
||||
b[2] = (token_srv >> 8) & 0xff
|
||||
b[3] = (token_srv) & 0xff
|
||||
b[4] = ((NET_PACKETFLAG_CONNLESS<<2)&0xfc) | (NET_PACKETVERSION&0x03)
|
||||
b[5] = (token_cl >> 24) & 0xff
|
||||
b[6] = (token_cl >> 16) & 0xff
|
||||
b[7] = (token_cl >> 8) & 0xff
|
||||
b[8] = (token_cl) & 0xff
|
||||
return bytes(b)
|
||||
|
||||
# CVariableInt::Unpack from src/engine/shared/compression.cpp
|
||||
def unpack_int(b):
|
||||
l = list(b[:5])
|
||||
i = 0
|
||||
Sign = (l[i]>>6)&1;
|
||||
res = l[i] & 0x3F;
|
||||
|
||||
for _ in (0,):
|
||||
if not (l[i]&0x80):
|
||||
break
|
||||
i+=1
|
||||
res |= (l[i]&(0x7F))<<(6);
|
||||
|
||||
if not (l[i]&0x80):
|
||||
break
|
||||
i+=1
|
||||
res |= (l[i]&(0x7F))<<(6+7);
|
||||
|
||||
if not (l[i]&0x80):
|
||||
break
|
||||
i+=1
|
||||
res |= (l[i]&(0x7F))<<(6+7+7);
|
||||
|
||||
if not (l[i]&0x80):
|
||||
break
|
||||
i+=1
|
||||
res |= (l[i]&(0x7F))<<(6+7+7+7);
|
||||
|
||||
i += 1;
|
||||
res ^= -Sign
|
||||
return res, b[i:]
|
||||
|
||||
class Server_Info(threading.Thread):
|
||||
|
||||
def __init__(self, address, type):
|
||||
def __init__(self, address):
|
||||
self.address = address
|
||||
self.type = type
|
||||
self.finished = False
|
||||
threading.Thread.__init__(self, target = self.run)
|
||||
|
||||
def run(self):
|
||||
self.info = None
|
||||
if self.type == SERVERTYPE_NORMAL:
|
||||
self.info = get_server_info3(self.address)
|
||||
elif self.type == SERVERTYPE_LEGACY:
|
||||
self.info = get_server_info(self.address)
|
||||
if self.info:
|
||||
self.info = get_server_info2(self.address)
|
||||
self.info = get_server_info(self.address)
|
||||
self.finished = True
|
||||
|
||||
|
||||
def get_server_info(address):
|
||||
try:
|
||||
sock = socket(AF_INET, SOCK_DGRAM)
|
||||
sock.settimeout(TIMEOUT);
|
||||
sock.sendto(PACKET_GETINFO, address)
|
||||
sock.settimeout(TIMEOUT)
|
||||
token = random.randrange(0x100000000)
|
||||
|
||||
# Token request
|
||||
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
||||
data, addr = sock.recvfrom(1024)
|
||||
sock.close()
|
||||
token_cl, token_srv = unpack_control_msg_with_token(data)
|
||||
assert token_cl == token, "Server %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
||||
|
||||
data = data[14:] # skip header
|
||||
slots = data.split("\x00")
|
||||
|
||||
server_info = {}
|
||||
server_info["version"] = slots[0]
|
||||
server_info["name"] = slots[1]
|
||||
server_info["map"] = slots[2]
|
||||
server_info["gametype"] = slots[3]
|
||||
server_info["flags"] = int(slots[4])
|
||||
server_info["progression"] = int(slots[5])
|
||||
server_info["num_players"] = int(slots[6])
|
||||
server_info["max_players"] = int(slots[7])
|
||||
server_info["players"] = []
|
||||
|
||||
for i in xrange(0, server_info["num_players"]):
|
||||
player = {}
|
||||
player["name"] = slots[8+i*2]
|
||||
player["score"] = int(slots[8+i*2+1])
|
||||
server_info["players"].append(player)
|
||||
|
||||
return server_info
|
||||
|
||||
except:
|
||||
sock.close()
|
||||
return None
|
||||
|
||||
|
||||
def get_server_info2(address):
|
||||
try:
|
||||
sock = socket(AF_INET, SOCK_DGRAM)
|
||||
sock.settimeout(TIMEOUT);
|
||||
sock.sendto(PACKET_GETINFO2, address)
|
||||
# Get info request
|
||||
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETINFO + b'\x00', address)
|
||||
data, addr = sock.recvfrom(1024)
|
||||
head = header_connless(token_cl, token_srv) + PACKET_INFO + b'\x00'
|
||||
assert data[:len(head)] == head, "Server %s info header mismatch: %r != %r (expected)" % (address, data[:len(head)], head)
|
||||
sock.close()
|
||||
|
||||
data = data[14:] # skip header
|
||||
slots = data.split("\x00")
|
||||
data = data[len(head):] # skip header
|
||||
|
||||
slots = data.split(b"\x00", maxsplit=5)
|
||||
|
||||
server_info = {}
|
||||
server_info["token"] = slots[0]
|
||||
server_info["version"] = slots[1]
|
||||
server_info["name"] = slots[2]
|
||||
server_info["map"] = slots[3]
|
||||
server_info["gametype"] = slots[4]
|
||||
server_info["flags"] = int(slots[5])
|
||||
server_info["progression"] = int(slots[6])
|
||||
server_info["num_players"] = int(slots[7])
|
||||
server_info["max_players"] = int(slots[8])
|
||||
server_info["version"] = slots[0].decode()
|
||||
server_info["name"] = slots[1].decode()
|
||||
server_info["hostname"] = slots[2].decode()
|
||||
server_info["map"] = slots[3].decode()
|
||||
server_info["gametype"] = slots[4].decode()
|
||||
data = slots[5]
|
||||
# these integers should fit in one byte each
|
||||
server_info["flags"], server_info["skill"], server_info["num_players"], server_info["max_players"], server_info["num_clients"], server_info["max_clients"] = tuple(data[:6])
|
||||
data = data[6:]
|
||||
server_info["players"] = []
|
||||
|
||||
for i in xrange(0, server_info["num_players"]):
|
||||
for i in range(server_info["num_clients"]):
|
||||
player = {}
|
||||
player["name"] = slots[9+i*2]
|
||||
player["score"] = int(slots[9+i*2+1])
|
||||
server_info["players"].append(player)
|
||||
|
||||
return server_info
|
||||
|
||||
except:
|
||||
sock.close()
|
||||
return None
|
||||
|
||||
|
||||
def get_server_info3(address):
|
||||
try:
|
||||
sock = socket(AF_INET, SOCK_DGRAM)
|
||||
sock.settimeout(TIMEOUT);
|
||||
sock.sendto(PACKET_GETINFO3, address)
|
||||
data, addr = sock.recvfrom(1400)
|
||||
sock.close()
|
||||
|
||||
data = data[14:] # skip header
|
||||
slots = data.split("\x00")
|
||||
|
||||
server_info = {}
|
||||
server_info["token"] = slots[0]
|
||||
server_info["version"] = slots[1]
|
||||
server_info["name"] = slots[2]
|
||||
server_info["map"] = slots[3]
|
||||
server_info["gametype"] = slots[4]
|
||||
server_info["flags"] = int(slots[5])
|
||||
server_info["num_players"] = int(slots[6])
|
||||
server_info["max_players"] = int(slots[7])
|
||||
server_info["num_clients"] = int(slots[8])
|
||||
server_info["max_clients"] = int(slots[9])
|
||||
server_info["players"] = []
|
||||
|
||||
for i in xrange(0, server_info["num_clients"]):
|
||||
player = {}
|
||||
player["name"] = slots[10+i*5]
|
||||
player["clan"] = slots[10+i*5+1]
|
||||
player["country"] = int(slots[10+i*5+2])
|
||||
player["score"] = int(slots[10+i*5+3])
|
||||
if int(slots[10+i*5+4]):
|
||||
slots = data.split(b"\x00", maxsplit=2)
|
||||
player["name"] = slots[0].decode()
|
||||
player["clan"] = slots[1].decode()
|
||||
data = slots[2]
|
||||
player["country"], data = unpack_int(data)
|
||||
player["score"], data = unpack_int(data)
|
||||
is_player, data = unpack_int(data)
|
||||
if is_player:
|
||||
player["player"] = True
|
||||
else:
|
||||
player["player"] = False
|
||||
server_info["players"].append(player)
|
||||
|
||||
return server_info
|
||||
|
||||
except AssertionError as e:
|
||||
print(*e.args)
|
||||
except OSError as e: # Timeout
|
||||
print('> Server %s did not answer' % (address,))
|
||||
except:
|
||||
# import traceback
|
||||
# traceback.print_exc()
|
||||
pass
|
||||
finally:
|
||||
sock.close()
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class Master_Server_Info(threading.Thread):
|
||||
|
@ -165,7 +177,7 @@ class Master_Server_Info(threading.Thread):
|
|||
threading.Thread.__init__(self, target = self.run)
|
||||
|
||||
def run(self):
|
||||
self.servers = get_list(self.address) + get_list2(self.address)
|
||||
self.servers = get_list(self.address)
|
||||
self.finished = True
|
||||
|
||||
|
||||
|
@ -175,96 +187,88 @@ def get_list(address):
|
|||
try:
|
||||
sock = socket(AF_INET, SOCK_DGRAM)
|
||||
sock.settimeout(TIMEOUT)
|
||||
sock.sendto(PACKET_GETLIST, address)
|
||||
|
||||
token = random.randrange(0x100000000)
|
||||
|
||||
# Token request
|
||||
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
||||
data, addr = sock.recvfrom(1024)
|
||||
token_cl, token_srv = unpack_control_msg_with_token(data)
|
||||
assert token_cl == token, "Master %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
||||
|
||||
# Get list request
|
||||
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETLIST, addr)
|
||||
head = header_connless(token_cl, token_srv) + PACKET_LIST
|
||||
|
||||
while 1:
|
||||
data, addr = sock.recvfrom(1024)
|
||||
# Header should keep consistent
|
||||
assert data[:len(head)] == head, "Master %s list header mismatch: %r != %r (expected)" % (address, data[:len(head)], head)
|
||||
|
||||
data = data[14:]
|
||||
num_servers = len(data) / 6
|
||||
data = data[len(head):]
|
||||
num_servers = len(data) // 18
|
||||
|
||||
for n in range(0, num_servers):
|
||||
ip = ".".join(map(str, map(ord, data[n*6:n*6+4])))
|
||||
port = ord(data[n*6+5]) * 256 + ord(data[n*6+4])
|
||||
servers += [[(ip, port), SERVERTYPE_LEGACY]]
|
||||
# IPv4
|
||||
if data[n*18:n*18+12] == b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff":
|
||||
ip = ".".join(map(str, data[n*18+12:n*18+16]))
|
||||
# IPv6
|
||||
else:
|
||||
ip = ":".join(map(str, data[n*18:n*18+16]))
|
||||
port = ((data[n*18+16])<<8) + data[n*18+17]
|
||||
servers += [(ip, port)]
|
||||
|
||||
except AssertionError as e:
|
||||
print(*e.args)
|
||||
except OSError as e: # Timeout
|
||||
if not servers:
|
||||
print('> Master %s did not answer' % (address,))
|
||||
except:
|
||||
# import traceback
|
||||
# traceback.print_exc()
|
||||
sock.close()
|
||||
|
||||
return servers
|
||||
|
||||
if __name__ == '__main__':
|
||||
master_servers = []
|
||||
|
||||
for i in range(1, NUM_MASTERSERVERS+1):
|
||||
m = Master_Server_Info(("master%d.teeworlds.com"%i, MASTERSERVER_PORT))
|
||||
master_servers.append(m)
|
||||
m.start()
|
||||
time.sleep(0.001) # avoid issues
|
||||
|
||||
def get_list2(address):
|
||||
servers = []
|
||||
|
||||
try:
|
||||
sock = socket(AF_INET, SOCK_DGRAM)
|
||||
sock.settimeout(TIMEOUT)
|
||||
sock.sendto(PACKET_GETLIST2, address)
|
||||
while len(master_servers) != 0:
|
||||
if master_servers[0].finished == True:
|
||||
if master_servers[0].servers:
|
||||
servers += master_servers[0].servers
|
||||
del master_servers[0]
|
||||
time.sleep(0.001) # be nice
|
||||
|
||||
while 1:
|
||||
data, addr = sock.recvfrom(1400)
|
||||
|
||||
data = data[14:]
|
||||
num_servers = len(data) / 18
|
||||
servers_info = []
|
||||
|
||||
for n in range(0, num_servers):
|
||||
if data[n*18:n*18+12] == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff":
|
||||
ip = ".".join(map(str, map(ord, data[n*18+12:n*18+16])))
|
||||
else:
|
||||
ip = ":".join(map(str, map(ord, data[n*18:n*18+16])))
|
||||
port = (ord(data[n*18+16])<<8) + ord(data[n*18+17])
|
||||
servers += [[(ip, port), SERVERTYPE_NORMAL]]
|
||||
print(str(len(servers)) + " servers")
|
||||
|
||||
except:
|
||||
sock.close()
|
||||
for server in servers:
|
||||
s = Server_Info(server)
|
||||
servers_info.append(s)
|
||||
s.start()
|
||||
time.sleep(0.001) # avoid issues
|
||||
|
||||
return servers
|
||||
num_players = 0
|
||||
num_clients = 0
|
||||
|
||||
|
||||
|
||||
master_servers = []
|
||||
|
||||
for i in range(1, NUM_MASTERSERVERS+1):
|
||||
m = Master_Server_Info(("master%d.teeworlds.com"%i, MASTERSERVER_PORT))
|
||||
master_servers.append(m)
|
||||
m.start()
|
||||
time.sleep(0.001) # avoid issues
|
||||
|
||||
servers = []
|
||||
|
||||
while len(master_servers) != 0:
|
||||
if master_servers[0].finished == True:
|
||||
if master_servers[0].servers:
|
||||
servers += master_servers[0].servers
|
||||
del master_servers[0]
|
||||
time.sleep(0.001) # be nice
|
||||
|
||||
servers_info = []
|
||||
|
||||
print str(len(servers)) + " servers"
|
||||
|
||||
for server in servers:
|
||||
s = Server_Info(server[0], server[1])
|
||||
servers_info.append(s)
|
||||
s.start()
|
||||
time.sleep(0.001) # avoid issues
|
||||
|
||||
num_players = 0
|
||||
num_clients = 0
|
||||
|
||||
while len(servers_info) != 0:
|
||||
if servers_info[0].finished == True:
|
||||
|
||||
if servers_info[0].info:
|
||||
num_players += servers_info[0].info["num_players"]
|
||||
if servers_info[0].type == SERVERTYPE_NORMAL:
|
||||
while len(servers_info) != 0:
|
||||
if servers_info[0].finished == True:
|
||||
if servers_info[0].info:
|
||||
num_players += servers_info[0].info["num_players"]
|
||||
num_clients += servers_info[0].info["num_clients"]
|
||||
else:
|
||||
num_clients += servers_info[0].info["num_players"]
|
||||
|
||||
del servers_info[0]
|
||||
del servers_info[0]
|
||||
|
||||
time.sleep(0.001) # be nice
|
||||
time.sleep(0.001) # be nice
|
||||
|
||||
print str(num_players) + " players and " + str(num_clients-num_players) + " spectators"
|
||||
print(str(num_players) + " players and " + str(num_clients-num_players) + " spectators")
|
||||
|
|
|
@ -362,7 +362,10 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
|||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
if(pCommand->m_Flags&CCommandBuffer::TEXTFLAG_LINEARMIPMAPS)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData);
|
||||
}
|
||||
|
||||
|
|
|
@ -377,20 +377,6 @@ bool CClient::ConnectionProblems() const
|
|||
return m_NetClient.GotProblems() != 0;
|
||||
}
|
||||
|
||||
void CClient::DirectInput(int *pInput, int Size)
|
||||
{
|
||||
CMsgPacker Msg(NETMSG_INPUT, true);
|
||||
Msg.AddInt(m_AckGameTick);
|
||||
Msg.AddInt(m_PredTick);
|
||||
Msg.AddInt(Size);
|
||||
|
||||
for(int i = 0; i < Size/4; i++)
|
||||
Msg.AddInt(pInput[i]);
|
||||
|
||||
SendMsg(&Msg, 0);
|
||||
}
|
||||
|
||||
|
||||
void CClient::SendInput()
|
||||
{
|
||||
int64 Now = time_get();
|
||||
|
@ -418,6 +404,12 @@ void CClient::SendInput()
|
|||
for(int i = 0; i < Size/4; i++)
|
||||
Msg.AddInt(m_aInputs[m_CurrentInput].m_aData[i]);
|
||||
|
||||
int PingCorrection = 0;
|
||||
int64 TagTime;
|
||||
if(m_SnapshotStorage.Get(m_AckGameTick, &TagTime, 0, 0) >= 0)
|
||||
PingCorrection = (int)(((Now-TagTime)*1000)/time_freq());
|
||||
Msg.AddInt(PingCorrection);
|
||||
|
||||
m_CurrentInput++;
|
||||
m_CurrentInput%=200;
|
||||
|
||||
|
@ -836,9 +828,9 @@ int CClient::PlayerScoreComp(const void *a, const void *b)
|
|||
{
|
||||
CServerInfo::CClient *p0 = (CServerInfo::CClient *)a;
|
||||
CServerInfo::CClient *p1 = (CServerInfo::CClient *)b;
|
||||
if(p0->m_Player && !p1->m_Player)
|
||||
if(!(p0->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC) && (p1->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
|
||||
return -1;
|
||||
if(!p0->m_Player && p1->m_Player)
|
||||
if((p0->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC) && !(p1->m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
|
||||
return 1;
|
||||
if(p0->m_Score == p1->m_Score)
|
||||
return 0;
|
||||
|
@ -865,6 +857,8 @@ int CClient::UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pTo
|
|||
pInfo->m_MaxPlayers = pUnpacker->GetInt();
|
||||
pInfo->m_NumClients = pUnpacker->GetInt();
|
||||
pInfo->m_MaxClients = pUnpacker->GetInt();
|
||||
pInfo->m_NumBotPlayers = 0;
|
||||
pInfo->m_NumBotSpectators = 0;
|
||||
|
||||
// don't add invalid info to the server browser list
|
||||
if(pInfo->m_NumClients < 0 || pInfo->m_NumClients > MAX_CLIENTS || pInfo->m_MaxClients < 0 || pInfo->m_MaxClients > MAX_CLIENTS ||
|
||||
|
@ -875,14 +869,30 @@ int CClient::UnpackServerInfo(CUnpacker *pUnpacker, CServerInfo *pInfo, int *pTo
|
|||
if(!pToken)
|
||||
return 0;
|
||||
|
||||
int NumPlayers = 0;
|
||||
int NumClients = 0;
|
||||
for(int i = 0; i < pInfo->m_NumClients; i++)
|
||||
{
|
||||
str_copy(pInfo->m_aClients[i].m_aName, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aName));
|
||||
str_copy(pInfo->m_aClients[i].m_aClan, pUnpacker->GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(pInfo->m_aClients[i].m_aClan));
|
||||
pInfo->m_aClients[i].m_Country = pUnpacker->GetInt();
|
||||
pInfo->m_aClients[i].m_Score = pUnpacker->GetInt();
|
||||
pInfo->m_aClients[i].m_Player = pUnpacker->GetInt() != 0 ? true : false;
|
||||
pInfo->m_aClients[i].m_PlayerType = pUnpacker->GetInt()&CServerInfo::CClient::PLAYERFLAG_MASK;
|
||||
|
||||
if(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_BOT)
|
||||
{
|
||||
if(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC)
|
||||
pInfo->m_NumBotSpectators++;
|
||||
else
|
||||
pInfo->m_NumBotPlayers++;
|
||||
}
|
||||
|
||||
NumClients++;
|
||||
if(!(pInfo->m_aClients[i].m_PlayerType&CServerInfo::CClient::PLAYERFLAG_SPEC))
|
||||
NumPlayers++;
|
||||
}
|
||||
pInfo->m_NumPlayers = NumPlayers;
|
||||
pInfo->m_NumClients = NumClients;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1381,7 +1391,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
|||
m_GameTime.Init((GameTick-1)*time_freq()/50);
|
||||
m_aSnapshots[SNAP_PREV] = m_SnapshotStorage.m_pFirst;
|
||||
m_aSnapshots[SNAP_CURRENT] = m_SnapshotStorage.m_pLast;
|
||||
m_LocalStartTime = time_get();
|
||||
SetState(IClient::STATE_ONLINE);
|
||||
DemoRecorder_HandleAutoStart();
|
||||
}
|
||||
|
@ -1671,20 +1680,25 @@ void CClient::VersionUpdate()
|
|||
{
|
||||
if(m_VersionInfo.m_VersionServeraddr.m_Job.Status() == CJob::STATE_DONE)
|
||||
{
|
||||
CNetChunk Packet;
|
||||
if(m_VersionInfo.m_VersionServeraddr.m_Job.Result() == 0)
|
||||
{
|
||||
CNetChunk Packet;
|
||||
|
||||
mem_zero(&Packet, sizeof(Packet));
|
||||
mem_zero(&Packet, sizeof(Packet));
|
||||
|
||||
m_VersionInfo.m_VersionServeraddr.m_Addr.port = VERSIONSRV_PORT;
|
||||
m_VersionInfo.m_VersionServeraddr.m_Addr.port = VERSIONSRV_PORT;
|
||||
|
||||
Packet.m_ClientID = -1;
|
||||
Packet.m_Address = m_VersionInfo.m_VersionServeraddr.m_Addr;
|
||||
Packet.m_pData = VERSIONSRV_GETVERSION;
|
||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
|
||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
||||
Packet.m_ClientID = -1;
|
||||
Packet.m_Address = m_VersionInfo.m_VersionServeraddr.m_Addr;
|
||||
Packet.m_pData = VERSIONSRV_GETVERSION;
|
||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
|
||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
||||
|
||||
m_ContactClient.Send(&Packet);
|
||||
m_VersionInfo.m_State = CVersionInfo::STATE_READY;
|
||||
m_ContactClient.Send(&Packet);
|
||||
m_VersionInfo.m_State = CVersionInfo::STATE_READY;
|
||||
}
|
||||
else
|
||||
m_VersionInfo.m_State = CVersionInfo::STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2071,6 +2085,8 @@ void CClient::Run()
|
|||
m_pGraphics->Shutdown();
|
||||
m_pSound->Shutdown();
|
||||
|
||||
m_ServerBrowser.SaveServerlist();
|
||||
|
||||
// shutdown SDL
|
||||
{
|
||||
SDL_Quit();
|
||||
|
@ -2395,8 +2411,6 @@ void CClient::RegisterCommands()
|
|||
|
||||
// used for server browser update
|
||||
m_pConsole->Chain("br_filter_string", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("br_filter_gametype", ConchainServerBrowserUpdate, this);
|
||||
m_pConsole->Chain("br_filter_serveraddress", ConchainServerBrowserUpdate, this);
|
||||
|
||||
m_pConsole->Chain("gfx_screen", ConchainWindowScreen, this);
|
||||
m_pConsole->Chain("gfx_fullscreen", ConchainFullscreen, this);
|
||||
|
@ -2431,14 +2445,27 @@ void CClient::HandleTeeworldsConnectLink(const char *pConLink)
|
|||
int main(int argc, const char **argv) // ignore_convention
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
#ifdef CONF_RELEASE
|
||||
bool HideConsole = true;
|
||||
#else
|
||||
bool HideConsole = false;
|
||||
#endif
|
||||
for(int i = 1; i < argc; i++) // ignore_convention
|
||||
{
|
||||
if(str_comp("-c", argv[i]) == 0 || str_comp("--console", argv[i]) == 0) // ignore_convention
|
||||
{
|
||||
HideConsole = false;
|
||||
break;
|
||||
}
|
||||
if(str_comp("-s", argv[i]) == 0 || str_comp("--silent", argv[i]) == 0) // ignore_convention
|
||||
{
|
||||
FreeConsole();
|
||||
HideConsole = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(HideConsole)
|
||||
FreeConsole();
|
||||
#endif
|
||||
|
||||
bool UseDefaultConfig = false;
|
||||
|
|
|
@ -174,6 +174,7 @@ class CClient : public IClient, public CDemoPlayer::IListner
|
|||
STATE_INIT=0,
|
||||
STATE_START,
|
||||
STATE_READY,
|
||||
STATE_ERROR,
|
||||
};
|
||||
|
||||
int m_State;
|
||||
|
@ -211,7 +212,6 @@ public:
|
|||
|
||||
virtual IGraphics::CTextureHandle GetDebugFont() const { return m_DebugFont; }
|
||||
|
||||
void DirectInput(int *pInput, int Size);
|
||||
void SendInput();
|
||||
|
||||
// TODO: OPT: do this alot smarter!
|
||||
|
|
|
@ -360,6 +360,8 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig
|
|||
}
|
||||
if(Flags&IGraphics::TEXLOAD_MULTI_DIMENSION)
|
||||
Cmd.m_Flags |= CCommandBuffer::TEXFLAG_TEXTURE3D;
|
||||
if(Flags&IGraphics::TEXLOAD_NOMIPMAPS)
|
||||
Cmd.m_Flags |= CCommandBuffer::TEXTFLAG_LINEARMIPMAPS;
|
||||
|
||||
|
||||
// copy texture data
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
TEXFLAG_QUALITY = 4,
|
||||
TEXFLAG_TEXTURE3D = 8,
|
||||
TEXFLAG_TEXTURE2D = 16,
|
||||
TEXTFLAG_LINEARMIPMAPS = 32,
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <base/math.h>
|
||||
#include <base/system.h>
|
||||
|
||||
#include <engine/external/json-parser/json.h>
|
||||
|
||||
#include <engine/shared/config.h>
|
||||
#include <engine/shared/memheap.h>
|
||||
#include <engine/shared/network.h>
|
||||
|
@ -13,12 +15,15 @@
|
|||
#include <engine/engine.h>
|
||||
#include <engine/friends.h>
|
||||
#include <engine/masterserver.h>
|
||||
#include <engine/storage.h>
|
||||
|
||||
#include <mastersrv/mastersrv.h>
|
||||
|
||||
#include "serverbrowser.h"
|
||||
|
||||
|
||||
static const char *s_pFilename = "serverlist.json";
|
||||
|
||||
inline int AddrHash(const NETADDR *pAddr)
|
||||
{
|
||||
if(pAddr->type==NETTYPE_IPV4)
|
||||
|
@ -39,6 +44,7 @@ void CServerBrowser::CServerlist::Clear()
|
|||
m_ServerlistHeap.Reset();
|
||||
m_NumServers = 0;
|
||||
m_NumPlayers = 0;
|
||||
m_NumClients = 0;
|
||||
mem_zero(m_aServerlistIp, sizeof(m_aServerlistIp));
|
||||
}
|
||||
|
||||
|
@ -66,11 +72,13 @@ CServerBrowser::CServerBrowser()
|
|||
|
||||
m_ActServerlistType = 0;
|
||||
m_BroadcastTime = 0;
|
||||
m_MasterRefreshTime = 0;
|
||||
}
|
||||
|
||||
void CServerBrowser::Init(class CNetClient *pNetClient, const char *pNetVersion)
|
||||
{
|
||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||
m_pMasterServer = Kernel()->RequestInterface<IMasterServer>();
|
||||
m_pNetClient = pNetClient;
|
||||
|
||||
|
@ -88,6 +96,8 @@ void CServerBrowser::Set(const NETADDR &Addr, int SetType, int Token, const CSer
|
|||
if(!(m_RefreshFlags&IServerBrowser::REFRESHFLAG_INTERNET))
|
||||
return;
|
||||
|
||||
m_MasterRefreshTime = 0;
|
||||
|
||||
if(!Find(IServerBrowser::TYPE_INTERNET, Addr))
|
||||
{
|
||||
pEntry = Add(IServerBrowser::TYPE_INTERNET, Addr);
|
||||
|
@ -95,17 +105,18 @@ void CServerBrowser::Set(const NETADDR &Addr, int SetType, int Token, const CSer
|
|||
}
|
||||
}
|
||||
break;
|
||||
/*else if(Type == SET_FAV_ADD)
|
||||
{
|
||||
if(m_ServerlistType != IServerBrowser::TYPE_FAVORITES)
|
||||
return;
|
||||
|
||||
if(!Find(Addr))
|
||||
case SET_FAV_ADD:
|
||||
{
|
||||
pEntry = Add(Addr);
|
||||
QueueRequest(pEntry);
|
||||
if(!(m_RefreshFlags&IServerBrowser::REFRESHFLAG_INTERNET))
|
||||
return;
|
||||
|
||||
if(!Find(IServerBrowser::TYPE_INTERNET, Addr))
|
||||
{
|
||||
pEntry = Add(IServerBrowser::TYPE_INTERNET, Addr);
|
||||
QueueRequest(pEntry);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
case SET_TOKEN:
|
||||
{
|
||||
int Type;
|
||||
|
@ -116,7 +127,7 @@ void CServerBrowser::Set(const NETADDR &Addr, int SetType, int Token, const CSer
|
|||
Type = IServerBrowser::TYPE_INTERNET;
|
||||
pEntry = Find(Type, Addr);
|
||||
if(pEntry && (pEntry->m_InfoState != CServerEntry::STATE_PENDING || Token != pEntry->m_CurrentToken))
|
||||
pEntry = 0;
|
||||
pEntry = 0;
|
||||
}
|
||||
|
||||
// lan entry
|
||||
|
@ -125,7 +136,7 @@ void CServerBrowser::Set(const NETADDR &Addr, int SetType, int Token, const CSer
|
|||
Type = IServerBrowser::TYPE_LAN;
|
||||
pEntry = Add(Type, Addr);
|
||||
}
|
||||
|
||||
|
||||
// set info
|
||||
if(pEntry)
|
||||
{
|
||||
|
@ -172,10 +183,22 @@ void CServerBrowser::Update(bool ForceResort)
|
|||
m_pNetClient->Send(&Packet);
|
||||
}
|
||||
|
||||
m_MasterRefreshTime = Now;
|
||||
|
||||
if(g_Config.m_Debug)
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "requesting server list");
|
||||
}
|
||||
|
||||
// load server list backup from file in case the masters don't response
|
||||
if(m_MasterRefreshTime && m_MasterRefreshTime+2*Timeout < Now)
|
||||
{
|
||||
LoadServerlist();
|
||||
m_MasterRefreshTime = 0;
|
||||
|
||||
if(g_Config.m_Debug)
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", "using backup server list");
|
||||
}
|
||||
|
||||
// do timeouts
|
||||
pEntry = m_pFirstReqServer;
|
||||
while(1)
|
||||
|
@ -283,6 +306,10 @@ void CServerBrowser::Refresh(int RefreshFlags)
|
|||
if(RefreshFlags&IServerBrowser::REFRESHFLAG_INTERNET)
|
||||
{
|
||||
// clear out everything
|
||||
for(CServerEntry *pEntry = m_pFirstReqServer; pEntry; pEntry = pEntry->m_pNextReq)
|
||||
{
|
||||
m_pNetClient->PurgeStoredPacket(pEntry->m_TrackID);
|
||||
}
|
||||
m_aServerlist[IServerBrowser::TYPE_INTERNET].Clear();
|
||||
if(m_ActServerlistType == IServerBrowser::TYPE_INTERNET)
|
||||
m_ServerBrowserFilter.Clear();
|
||||
|
@ -291,13 +318,10 @@ void CServerBrowser::Refresh(int RefreshFlags)
|
|||
m_NumRequests = 0;
|
||||
|
||||
m_NeedRefresh = 1;
|
||||
for(int i = 0; i < m_ServerBrowserFavorites.m_NumFavoriteServers; i++)
|
||||
if(m_ServerBrowserFavorites.m_aFavoriteServers[i].m_State >= CServerBrowserFavorites::FAVSTATE_ADDR)
|
||||
Set(m_ServerBrowserFavorites.m_aFavoriteServers[i].m_Addr, SET_FAV_ADD, -1, 0);
|
||||
}
|
||||
/*else if(Type == IServerBrowser::TYPE_FAVORITES)
|
||||
{
|
||||
for(int i = 0; i < m_NumFavoriteServers; i++)
|
||||
if(m_aFavoriteServers[i].m_State >= FAVSTATE_ADDR)
|
||||
Set(m_aFavoriteServers[i].m_Addr, SET_FAV_ADD, -1, 0);
|
||||
}*/
|
||||
}
|
||||
|
||||
int CServerBrowser::LoadingProgression() const
|
||||
|
@ -330,7 +354,7 @@ void CServerBrowser::AddFavorite(const CServerInfo *pInfo)
|
|||
}
|
||||
|
||||
void CServerBrowser::RemoveFavorite(const CServerInfo *pInfo)
|
||||
{
|
||||
{
|
||||
if(m_ServerBrowserFavorites.RemoveFavoriteEx(pInfo->m_aHostname, &pInfo->m_NetAddr))
|
||||
{
|
||||
for(int i = 0; i < NUM_TYPES; ++i)
|
||||
|
@ -445,7 +469,29 @@ void CServerBrowser::RemoveRequest(CServerEntry *pEntry)
|
|||
}
|
||||
}
|
||||
|
||||
void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const
|
||||
void CServerBrowser::CBFTrackPacket(int TrackID, void *pCallbackUser)
|
||||
{
|
||||
if(!pCallbackUser)
|
||||
return;
|
||||
|
||||
CServerBrowser *pSelf = (CServerBrowser *)pCallbackUser;
|
||||
CServerEntry *pEntry = pSelf->m_pFirstReqServer;
|
||||
while(1)
|
||||
{
|
||||
if(!pEntry) // no more entries
|
||||
break;
|
||||
|
||||
if(pEntry->m_TrackID == TrackID) // got it -> update
|
||||
{
|
||||
pEntry->m_RequestTime = time_get();
|
||||
break;
|
||||
}
|
||||
|
||||
pEntry = pEntry->m_pNextReq;
|
||||
}
|
||||
}
|
||||
|
||||
void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry)
|
||||
{
|
||||
if(g_Config.m_Debug)
|
||||
{
|
||||
|
@ -460,15 +506,18 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) cons
|
|||
Packer.Reset();
|
||||
Packer.AddRaw(SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
|
||||
Packer.AddInt(pEntry ? pEntry->m_CurrentToken : m_CurrentLanToken);
|
||||
|
||||
|
||||
CNetChunk Packet;
|
||||
Packet.m_ClientID = -1;
|
||||
Packet.m_Address = Addr;
|
||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
||||
Packet.m_DataSize = Packer.Size();
|
||||
Packet.m_pData = Packer.Data();
|
||||
|
||||
m_pNetClient->Send(&Packet);
|
||||
CSendCBData Data;
|
||||
Data.m_pfnCallback = CBFTrackPacket;
|
||||
Data.m_pCallbackUser = this;
|
||||
m_pNetClient->Send(&Packet, NET_TOKEN_NONE, &Data);
|
||||
pEntry->m_TrackID = Data.m_TrackID;
|
||||
|
||||
if(pEntry)
|
||||
{
|
||||
|
@ -483,7 +532,7 @@ void CServerBrowser::SetInfo(int ServerlistType, CServerEntry *pEntry, const CSe
|
|||
pEntry->m_Info = Info;
|
||||
pEntry->m_Info.m_Flags &= FLAG_PASSWORD;
|
||||
if(str_comp(pEntry->m_Info.m_aGameType, "DM") == 0 || str_comp(pEntry->m_Info.m_aGameType, "TDM") == 0 || str_comp(pEntry->m_Info.m_aGameType, "CTF") == 0 ||
|
||||
str_comp(pEntry->m_Info.m_aGameType, "SUR") == 0 || str_comp(pEntry->m_Info.m_aGameType, "LMS") == 0)
|
||||
str_comp(pEntry->m_Info.m_aGameType, "LTS") == 0 || str_comp(pEntry->m_Info.m_aGameType, "LMS") == 0)
|
||||
pEntry->m_Info.m_Flags |= FLAG_PURE;
|
||||
if(str_comp(pEntry->m_Info.m_aMap, "dm1") == 0 || str_comp(pEntry->m_Info.m_aMap, "dm2") == 0 || str_comp(pEntry->m_Info.m_aMap, "dm3") == 0 ||
|
||||
str_comp(pEntry->m_Info.m_aMap, "dm6") == 0 || str_comp(pEntry->m_Info.m_aMap, "dm7") == 0 || str_comp(pEntry->m_Info.m_aMap, "dm8") == 0 ||
|
||||
|
@ -491,12 +540,79 @@ void CServerBrowser::SetInfo(int ServerlistType, CServerEntry *pEntry, const CSe
|
|||
str_comp(pEntry->m_Info.m_aMap, "ctf1") == 0 || str_comp(pEntry->m_Info.m_aMap, "ctf2") == 0 || str_comp(pEntry->m_Info.m_aMap, "ctf3") == 0 ||
|
||||
str_comp(pEntry->m_Info.m_aMap, "ctf4") == 0 || str_comp(pEntry->m_Info.m_aMap, "ctf5") == 0 || str_comp(pEntry->m_Info.m_aMap, "ctf6") == 0 ||
|
||||
str_comp(pEntry->m_Info.m_aMap, "ctf7") == 0 || str_comp(pEntry->m_Info.m_aMap, "ctf8") == 0 ||
|
||||
str_comp(pEntry->m_Info.m_aMap, "sur1") == 0)
|
||||
str_comp(pEntry->m_Info.m_aMap, "lms1") == 0)
|
||||
pEntry->m_Info.m_Flags |= FLAG_PUREMAP;
|
||||
pEntry->m_Info.m_Favorite = Fav;
|
||||
pEntry->m_Info.m_NetAddr = pEntry->m_Addr;
|
||||
|
||||
|
||||
m_aServerlist[ServerlistType].m_NumPlayers += pEntry->m_Info.m_NumPlayers;
|
||||
m_aServerlist[ServerlistType].m_NumClients += pEntry->m_Info.m_NumClients;
|
||||
|
||||
pEntry->m_InfoState = CServerEntry::STATE_READY;
|
||||
}
|
||||
|
||||
void CServerBrowser::LoadServerlist()
|
||||
{
|
||||
// read file data into buffer
|
||||
IOHANDLE File = Storage()->OpenFile(s_pFilename, IOFLAG_READ, IStorage::TYPE_ALL);
|
||||
if(!File)
|
||||
return;
|
||||
int FileSize = (int)io_length(File);
|
||||
char *pFileData = (char *)mem_alloc(FileSize, 1);
|
||||
io_read(File, pFileData, FileSize);
|
||||
io_close(File);
|
||||
|
||||
// parse json data
|
||||
json_settings JsonSettings;
|
||||
mem_zero(&JsonSettings, sizeof(JsonSettings));
|
||||
char aError[256];
|
||||
json_value *pJsonData = json_parse_ex(&JsonSettings, pFileData, FileSize, aError);
|
||||
mem_free(pFileData);
|
||||
|
||||
if(pJsonData == 0)
|
||||
{
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, s_pFilename, aError);
|
||||
return;
|
||||
}
|
||||
|
||||
// extract server list
|
||||
const json_value &rEntry = (*pJsonData)["serverlist"];
|
||||
for(unsigned i = 0; i < rEntry.u.array.length; ++i)
|
||||
{
|
||||
if(rEntry[i].type == json_string)
|
||||
{
|
||||
NETADDR Addr = { 0 };
|
||||
if(!net_addr_from_str(&Addr, rEntry[i]))
|
||||
Set(Addr, SET_MASTER_ADD, -1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
json_value_free(pJsonData);
|
||||
}
|
||||
|
||||
void CServerBrowser::SaveServerlist()
|
||||
{
|
||||
IOHANDLE File = Storage()->OpenFile(s_pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
||||
if(!File)
|
||||
return;
|
||||
|
||||
char aBuf[512];
|
||||
|
||||
// server list
|
||||
const char *p = "{\"serverlist\": [\n";
|
||||
io_write(File, p, str_length(p));
|
||||
|
||||
for(int i = 0; i < m_aServerlist[IServerBrowser::TYPE_INTERNET].m_NumServers; ++i)
|
||||
{
|
||||
// entry
|
||||
str_format(aBuf, sizeof(aBuf), "\t\"%s\",\n", m_aServerlist[IServerBrowser::TYPE_INTERNET].m_ppServerlist[i]->m_Info.m_aAddress);
|
||||
io_write(File, aBuf, str_length(aBuf));
|
||||
}
|
||||
|
||||
// server list end
|
||||
p = "\t]\n}\n";
|
||||
io_write(File, p, str_length(p));
|
||||
|
||||
io_close(File);
|
||||
}
|
||||
|
|
|
@ -32,9 +32,11 @@ public:
|
|||
|
||||
int NumServers() const { return m_aServerlist[m_ActServerlistType].m_NumServers; }
|
||||
int NumPlayers() const { return m_aServerlist[m_ActServerlistType].m_NumPlayers; }
|
||||
int NumClients() const { return m_aServerlist[m_ActServerlistType].m_NumClients; }
|
||||
const CServerInfo *Get(int Index) const { return &m_aServerlist[m_ActServerlistType].m_ppServerlist[Index]->m_Info; };
|
||||
|
||||
int NumSortedServers(int Index) const { return m_ServerBrowserFilter.GetNumSortedServers(Index); }
|
||||
int NumSortedPlayers(int Index) const { return m_ServerBrowserFilter.GetNumSortedPlayers(Index); }
|
||||
int NumSortedServers(int FilterIndex) const { return m_ServerBrowserFilter.GetNumSortedServers(FilterIndex); }
|
||||
int NumSortedPlayers(int FilterIndex) const { return m_ServerBrowserFilter.GetNumSortedPlayers(FilterIndex); }
|
||||
const CServerInfo *SortedGet(int FilterIndex, int Index) const { return &m_aServerlist[m_ActServerlistType].m_ppServerlist[m_ServerBrowserFilter.GetIndex(FilterIndex, Index)]->m_Info; };
|
||||
const void *GetID(int FilterIndex, int Index) const { return m_ServerBrowserFilter.GetID(FilterIndex, Index); };
|
||||
|
||||
|
@ -47,14 +49,23 @@ public:
|
|||
void GetFilter(int Index, CServerFilterInfo *pFilterInfo) { m_ServerBrowserFilter.GetFilter(Index, pFilterInfo); };
|
||||
void RemoveFilter(int Index) { m_ServerBrowserFilter.RemoveFilter(Index); };
|
||||
|
||||
static void CBFTrackPacket(int TrackID, void *pUser);
|
||||
|
||||
void LoadServerlist();
|
||||
void SaveServerlist();
|
||||
|
||||
private:
|
||||
class CNetClient *m_pNetClient;
|
||||
class IConsole *m_pConsole;
|
||||
class IStorage *m_pStorage;
|
||||
class IMasterServer *m_pMasterServer;
|
||||
|
||||
class CServerBrowserFavorites m_ServerBrowserFavorites;
|
||||
class CServerBrowserFilter m_ServerBrowserFilter;
|
||||
|
||||
class IConsole *Console() const { return m_pConsole; }
|
||||
class IStorage *Storage() const { return m_pStorage; }
|
||||
|
||||
// serverlist
|
||||
int m_ActServerlistType;
|
||||
class CServerlist
|
||||
|
@ -62,6 +73,7 @@ private:
|
|||
public:
|
||||
class CHeap m_ServerlistHeap;
|
||||
|
||||
int m_NumClients;
|
||||
int m_NumPlayers;
|
||||
int m_NumServers;
|
||||
int m_NumServerCapacity;
|
||||
|
@ -83,12 +95,13 @@ private:
|
|||
|
||||
int m_RefreshFlags;
|
||||
int64 m_BroadcastTime;
|
||||
int64 m_MasterRefreshTime;
|
||||
|
||||
CServerEntry *Add(int ServerlistType, const NETADDR &Addr);
|
||||
CServerEntry *Find(int ServerlistType, const NETADDR &Addr);
|
||||
void QueueRequest(CServerEntry *pEntry);
|
||||
void RemoveRequest(CServerEntry *pEntry);
|
||||
void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) const;
|
||||
void RequestImpl(const NETADDR &Addr, CServerEntry *pEntry);
|
||||
void SetInfo(int ServerlistType, CServerEntry *pEntry, const CServerInfo &Info);
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
int64 m_RequestTime;
|
||||
int m_InfoState;
|
||||
int m_CurrentToken; // the token is to keep server refresh separated from each other
|
||||
int m_TrackID;
|
||||
class CServerInfo m_Info;
|
||||
|
||||
CServerEntry *m_pNextIp; // ip hashed list
|
||||
|
|
|
@ -28,11 +28,13 @@ CServerBrowserFilter::CServerFilter::CServerFilter()
|
|||
{
|
||||
m_pServerBrowserFilter = 0;
|
||||
|
||||
m_SortHash = 0;
|
||||
m_Ping = 0;
|
||||
m_Country = 0;
|
||||
m_aGametype[0] = 0;
|
||||
m_aServerAddress[0] = 0;
|
||||
m_FilterInfo.m_SortHash = 0;
|
||||
m_FilterInfo.m_Ping = 0;
|
||||
m_FilterInfo.m_Country = 0;
|
||||
m_FilterInfo.m_ServerLevel = 0;
|
||||
for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i)
|
||||
m_FilterInfo.m_aGametype[i][0] = 0;
|
||||
m_FilterInfo.m_aAddress[0] = 0;
|
||||
|
||||
m_NumSortedPlayers = 0;
|
||||
m_NumSortedServers = 0;
|
||||
|
@ -43,7 +45,37 @@ CServerBrowserFilter::CServerFilter::CServerFilter()
|
|||
|
||||
CServerBrowserFilter::CServerFilter::~CServerFilter()
|
||||
{
|
||||
mem_free(m_pSortedServerlist);
|
||||
if(m_pSortedServerlist)
|
||||
mem_free(m_pSortedServerlist);
|
||||
}
|
||||
|
||||
CServerBrowserFilter::CServerFilter& CServerBrowserFilter::CServerFilter::operator=(const CServerBrowserFilter::CServerFilter& Other)
|
||||
{
|
||||
if(&Other != this)
|
||||
{
|
||||
m_pServerBrowserFilter = Other.m_pServerBrowserFilter;
|
||||
m_FilterInfo.m_SortHash = Other.m_FilterInfo.m_SortHash;
|
||||
m_FilterInfo.m_Ping = Other.m_FilterInfo.m_Ping;
|
||||
m_FilterInfo.m_Country = Other.m_FilterInfo.m_Country;
|
||||
m_FilterInfo.m_ServerLevel = Other.m_FilterInfo.m_ServerLevel;
|
||||
for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i)
|
||||
{
|
||||
if(Other.m_FilterInfo.m_aGametype[i][0])
|
||||
str_copy(m_FilterInfo.m_aGametype[i], Other.m_FilterInfo.m_aGametype[i], sizeof(m_FilterInfo.m_aGametype[i]));
|
||||
else
|
||||
m_FilterInfo.m_aGametype[i][0] = 0;
|
||||
}
|
||||
str_copy(m_FilterInfo.m_aAddress, Other.m_FilterInfo.m_aAddress, sizeof(m_FilterInfo.m_aAddress));
|
||||
|
||||
m_NumSortedPlayers = Other.m_NumSortedPlayers;
|
||||
m_NumSortedServers = Other.m_NumSortedServers;
|
||||
m_SortedServersCapacity = Other.m_SortedServersCapacity;
|
||||
|
||||
m_pSortedServerlist = (int *)mem_alloc(m_SortedServersCapacity * sizeof(int), 1);
|
||||
for(int i = 0; i < m_SortedServersCapacity; ++i)
|
||||
m_pSortedServerlist[i] = Other.m_pSortedServerlist[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CServerBrowserFilter::CServerFilter::Filter()
|
||||
|
@ -66,38 +98,51 @@ void CServerBrowserFilter::CServerFilter::Filter()
|
|||
{
|
||||
int Filtered = 0;
|
||||
|
||||
if(m_SortHash&IServerBrowser::FILTER_EMPTY && ((m_SortHash&IServerBrowser::FILTER_SPECTATORS && m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers == 0) || m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients == 0))
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_EMPTY && ((m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS && m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers == 0) || m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients == 0))
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_FULL && ((m_SortHash&IServerBrowser::FILTER_SPECTATORS && m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers == m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_MaxPlayers) ||
|
||||
else if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FULL && ((m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS && m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers == m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_MaxPlayers) ||
|
||||
m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients == m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_MaxClients))
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_PW && m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Flags&IServerBrowser::FLAG_PASSWORD)
|
||||
else if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PW && m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Flags&IServerBrowser::FLAG_PASSWORD)
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_FAVORITE && !m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Favorite)
|
||||
else if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FAVORITE && !m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Favorite)
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_PURE && !(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Flags&IServerBrowser::FLAG_PURE))
|
||||
else if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE && !(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Flags&IServerBrowser::FLAG_PURE))
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_PURE_MAP && !(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Flags&IServerBrowser::FLAG_PUREMAP))
|
||||
else if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE_MAP && !(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Flags&IServerBrowser::FLAG_PUREMAP))
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_PING && m_Ping < m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Latency)
|
||||
else if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PING && m_FilterInfo.m_Ping < m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_Latency)
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_COMPAT_VERSION && str_comp_num(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aVersion, m_pServerBrowserFilter->m_aNetVersion, 3) != 0)
|
||||
else if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_COMPAT_VERSION && str_comp_num(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aVersion, m_pServerBrowserFilter->m_aNetVersion, 3) != 0)
|
||||
Filtered = 1;
|
||||
else if(m_aServerAddress[0] && !str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aAddress, m_aServerAddress))
|
||||
else if(m_FilterInfo.m_aAddress[0] && !str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aAddress, m_FilterInfo.m_aAddress))
|
||||
Filtered = 1;
|
||||
else if(m_SortHash&IServerBrowser::FILTER_GAMETYPE_STRICT && m_aGametype[0] && str_comp_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_aGametype))
|
||||
Filtered = 1;
|
||||
else if(!(m_SortHash&IServerBrowser::FILTER_GAMETYPE_STRICT) && m_aGametype[0] && !str_find_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_aGametype))
|
||||
else if(m_FilterInfo.m_ServerLevel & (1 << m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_ServerLevel))
|
||||
Filtered = 1;
|
||||
else
|
||||
{
|
||||
if(m_SortHash&IServerBrowser::FILTER_COUNTRY)
|
||||
if(m_FilterInfo.m_aGametype[0][0])
|
||||
{
|
||||
Filtered = 1;
|
||||
for(int Index = 0; Index < CServerFilterInfo::MAX_GAMETYPES; ++Index)
|
||||
{
|
||||
if(!m_FilterInfo.m_aGametype[Index][0])
|
||||
break;
|
||||
if(!str_comp_nocase(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aGameType, m_FilterInfo.m_aGametype[Index]))
|
||||
{
|
||||
Filtered = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY)
|
||||
{
|
||||
Filtered = 1;
|
||||
// match against player country
|
||||
for(int p = 0; p < m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients; p++)
|
||||
{
|
||||
if(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_Country == m_Country)
|
||||
if(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_Country == m_FilterInfo.m_Country)
|
||||
{
|
||||
Filtered = 0;
|
||||
break;
|
||||
|
@ -153,10 +198,18 @@ void CServerBrowserFilter::CServerFilter::Filter()
|
|||
m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_FriendState = max(m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_FriendState, m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_aClients[p].m_FriendState);
|
||||
}
|
||||
|
||||
if(!(m_SortHash&IServerBrowser::FILTER_FRIENDS) || m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_FriendState != IFriends::FRIEND_NO)
|
||||
if(!(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FRIENDS) || m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_FriendState != IFriends::FRIEND_NO)
|
||||
{
|
||||
m_pSortedServerlist[m_NumSortedServers++] = i;
|
||||
m_NumSortedPlayers += (m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers : m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients;
|
||||
|
||||
int Count = (m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumPlayers : m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumClients;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS)
|
||||
{
|
||||
Count -= m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumBotPlayers;
|
||||
if(!(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS))
|
||||
Count -= m_pServerBrowserFilter->m_ppServerlist[i]->m_Info.m_NumBotSpectators;
|
||||
}
|
||||
m_NumSortedPlayers += Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,20 +217,20 @@ void CServerBrowserFilter::CServerFilter::Filter()
|
|||
|
||||
int CServerBrowserFilter::CServerFilter::GetSortHash() const
|
||||
{
|
||||
int i = g_Config.m_BrSort&0xf;
|
||||
i |= g_Config.m_BrSortOrder<<4;
|
||||
if(m_SortHash&IServerBrowser::FILTER_EMPTY) i |= 1<<5;
|
||||
if(m_SortHash&IServerBrowser::FILTER_FULL) i |= 1<<6;
|
||||
if(m_SortHash&IServerBrowser::FILTER_SPECTATORS) i |= 1<<7;
|
||||
if(m_SortHash&IServerBrowser::FILTER_FRIENDS) i |= 1<<8;
|
||||
if(m_SortHash&IServerBrowser::FILTER_PW) i |= 1<<9;
|
||||
if(m_SortHash&IServerBrowser::FILTER_FAVORITE) i |= 1<<10;
|
||||
if(m_SortHash&IServerBrowser::FILTER_COMPAT_VERSION) i |= 1<<11;
|
||||
if(m_SortHash&IServerBrowser::FILTER_PURE) i |= 1<<12;
|
||||
if(m_SortHash&IServerBrowser::FILTER_PURE_MAP) i |= 1<<13;
|
||||
if(m_SortHash&IServerBrowser::FILTER_GAMETYPE_STRICT) i |= 1<<14;
|
||||
if(m_SortHash&IServerBrowser::FILTER_COUNTRY) i |= 1<<15;
|
||||
if(m_SortHash&IServerBrowser::FILTER_PING) i |= 1<<16;
|
||||
int i = g_Config.m_BrSort&0x7;
|
||||
i |= g_Config.m_BrSortOrder<<3;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_BOTS) i |= 1 << 4;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_EMPTY) i |= 1<<5;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FULL) i |= 1<<6;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) i |= 1<<7;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FRIENDS) i |= 1<<8;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PW) i |= 1<<9;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FAVORITE) i |= 1<<10;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_COMPAT_VERSION) i |= 1<<11;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE) i |= 1<<12;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE_MAP) i |= 1<<13;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY) i |= 1<<14;
|
||||
if(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_PING) i |= 1<<15;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -200,13 +253,13 @@ void CServerBrowserFilter::CServerFilter::Sort()
|
|||
break;
|
||||
case IServerBrowser::SORT_NUMPLAYERS:
|
||||
std::stable_sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this,
|
||||
(m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? &CServerBrowserFilter::CServerFilter::SortCompareNumPlayers : &CServerBrowserFilter::CServerFilter::SortCompareNumClients));
|
||||
(m_FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS) ? &CServerBrowserFilter::CServerFilter::SortCompareNumPlayers : &CServerBrowserFilter::CServerFilter::SortCompareNumClients));
|
||||
break;
|
||||
case IServerBrowser::SORT_GAMETYPE:
|
||||
std::stable_sort(m_pSortedServerlist, m_pSortedServerlist+m_NumSortedServers, SortWrap(this, &CServerBrowserFilter::CServerFilter::SortCompareGametype));
|
||||
}
|
||||
|
||||
m_SortHash = GetSortHash();
|
||||
m_FilterInfo.m_SortHash = GetSortHash();
|
||||
}
|
||||
|
||||
bool CServerBrowserFilter::CServerFilter::SortCompareName(int Index1, int Index2) const
|
||||
|
@ -281,7 +334,7 @@ void CServerBrowserFilter::Sort(CServerEntry **ppServerlist, int NumServers, int
|
|||
{
|
||||
// check if we need to resort
|
||||
CServerFilter *pFilter = &m_lFilters[i];
|
||||
if((ResortFlags&RESORT_FLAG_FORCE) || ((ResortFlags&RESORT_FLAG_FAV) && pFilter->m_SortHash&IServerBrowser::FILTER_FAVORITE) || pFilter->m_SortHash != pFilter->GetSortHash())
|
||||
if((ResortFlags&RESORT_FLAG_FORCE) || ((ResortFlags&RESORT_FLAG_FAV) && pFilter->m_FilterInfo.m_SortHash&IServerBrowser::FILTER_FAVORITE) || pFilter->m_FilterInfo.m_SortHash != pFilter->GetSortHash())
|
||||
pFilter->Sort();
|
||||
}
|
||||
}
|
||||
|
@ -289,11 +342,13 @@ void CServerBrowserFilter::Sort(CServerEntry **ppServerlist, int NumServers, int
|
|||
int CServerBrowserFilter::AddFilter(const CServerFilterInfo *pFilterInfo)
|
||||
{
|
||||
CServerFilter Filter;
|
||||
Filter.m_SortHash = pFilterInfo->m_SortHash;
|
||||
Filter.m_Ping = pFilterInfo->m_Ping;
|
||||
Filter.m_Country = pFilterInfo->m_Country;
|
||||
str_copy(Filter.m_aGametype, pFilterInfo->m_aGametype, sizeof(Filter.m_aGametype));
|
||||
str_copy(Filter.m_aServerAddress, pFilterInfo->m_aAddress, sizeof(Filter.m_aServerAddress));
|
||||
Filter.m_FilterInfo.m_SortHash = pFilterInfo->m_SortHash;
|
||||
Filter.m_FilterInfo.m_Ping = pFilterInfo->m_Ping;
|
||||
Filter.m_FilterInfo.m_Country = pFilterInfo->m_Country;
|
||||
Filter.m_FilterInfo.m_ServerLevel = pFilterInfo->m_ServerLevel;
|
||||
for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i)
|
||||
str_copy(Filter.m_FilterInfo.m_aGametype[i], pFilterInfo->m_aGametype[i], sizeof(Filter.m_FilterInfo.m_aGametype[i]));
|
||||
str_copy(Filter.m_FilterInfo.m_aAddress, pFilterInfo->m_aAddress, sizeof(Filter.m_FilterInfo.m_aAddress));
|
||||
Filter.m_pSortedServerlist = 0;
|
||||
Filter.m_NumSortedPlayers = 0;
|
||||
Filter.m_NumSortedServers = 0;
|
||||
|
@ -307,21 +362,25 @@ int CServerBrowserFilter::AddFilter(const CServerFilterInfo *pFilterInfo)
|
|||
void CServerBrowserFilter::GetFilter(int Index, CServerFilterInfo *pFilterInfo) const
|
||||
{
|
||||
const CServerFilter *pFilter = &m_lFilters[Index];
|
||||
pFilterInfo->m_SortHash = pFilter->m_SortHash;
|
||||
pFilterInfo->m_Ping = pFilter->m_Ping;
|
||||
pFilterInfo->m_Country = pFilter->m_Country;
|
||||
str_copy(pFilterInfo->m_aGametype, pFilter->m_aGametype, sizeof(pFilterInfo->m_aGametype));
|
||||
str_copy(pFilterInfo->m_aAddress, pFilter->m_aServerAddress, sizeof(pFilterInfo->m_aAddress));
|
||||
pFilterInfo->m_SortHash = pFilter->m_FilterInfo.m_SortHash;
|
||||
pFilterInfo->m_Ping = pFilter->m_FilterInfo.m_Ping;
|
||||
pFilterInfo->m_Country = pFilter->m_FilterInfo.m_Country;
|
||||
pFilterInfo->m_ServerLevel = pFilter->m_FilterInfo.m_ServerLevel;
|
||||
for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i)
|
||||
str_copy(pFilterInfo->m_aGametype[i], pFilter->m_FilterInfo.m_aGametype[i], sizeof(pFilterInfo->m_aGametype[i]));
|
||||
str_copy(pFilterInfo->m_aAddress, pFilter->m_FilterInfo.m_aAddress, sizeof(pFilterInfo->m_aAddress));
|
||||
}
|
||||
|
||||
void CServerBrowserFilter::SetFilter(int Index, const CServerFilterInfo *pFilterInfo)
|
||||
{
|
||||
CServerFilter *pFilter = &m_lFilters[Index];
|
||||
pFilter->m_SortHash = pFilterInfo->m_SortHash;
|
||||
pFilter->m_Ping = pFilterInfo->m_Ping;
|
||||
pFilter->m_Country = pFilterInfo->m_Country;
|
||||
str_copy(pFilter->m_aGametype, pFilterInfo->m_aGametype, sizeof(pFilter->m_aGametype));
|
||||
str_copy(pFilter->m_aServerAddress, pFilterInfo->m_aAddress, sizeof(pFilter->m_aServerAddress));
|
||||
pFilter->m_FilterInfo.m_SortHash = pFilterInfo->m_SortHash;
|
||||
pFilter->m_FilterInfo.m_Ping = pFilterInfo->m_Ping;
|
||||
pFilter->m_FilterInfo.m_Country = pFilterInfo->m_Country;
|
||||
pFilter->m_FilterInfo.m_ServerLevel = pFilterInfo->m_ServerLevel;
|
||||
for(int i = 0; i < CServerFilterInfo::MAX_GAMETYPES; ++i)
|
||||
str_copy(pFilter->m_FilterInfo.m_aGametype[i], pFilterInfo->m_aGametype[i], sizeof(pFilter->m_FilterInfo.m_aGametype[i]));
|
||||
str_copy(pFilter->m_FilterInfo.m_aAddress, pFilterInfo->m_aAddress, sizeof(pFilter->m_FilterInfo.m_aAddress));
|
||||
|
||||
pFilter->Sort();
|
||||
}
|
||||
|
|
|
@ -20,11 +20,7 @@ public:
|
|||
CServerBrowserFilter *m_pServerBrowserFilter;
|
||||
|
||||
// filter settings
|
||||
int m_SortHash;
|
||||
int m_Ping;
|
||||
int m_Country;
|
||||
char m_aGametype[32];
|
||||
char m_aServerAddress[NETADDR_MAXSTRSIZE];
|
||||
CServerFilterInfo m_FilterInfo;
|
||||
|
||||
// stats
|
||||
int m_NumSortedPlayers;
|
||||
|
@ -34,6 +30,7 @@ public:
|
|||
|
||||
CServerFilter();
|
||||
~CServerFilter();
|
||||
CServerFilter& operator=(const CServerFilter& Other);
|
||||
|
||||
void Filter();
|
||||
int GetSortHash() const;
|
||||
|
@ -62,8 +59,8 @@ public:
|
|||
// stats
|
||||
const void *GetID(int FilterIndex, int Index) const { return &m_lFilters[FilterIndex].m_pSortedServerlist[Index]; }
|
||||
int GetIndex(int FilterIndex, int Index) const { return m_lFilters[FilterIndex].m_pSortedServerlist[Index]; }
|
||||
int GetNumSortedServers(int Index) const { return m_lFilters[Index].m_NumSortedServers; }
|
||||
int GetNumSortedPlayers(int Index) const { return m_lFilters[Index].m_NumSortedPlayers; }
|
||||
int GetNumSortedServers(int FilterIndex) const { return m_lFilters[FilterIndex].m_NumSortedServers; }
|
||||
int GetNumSortedPlayers(int FilterIndex) const { return m_lFilters[FilterIndex].m_NumSortedPlayers; }
|
||||
|
||||
private:
|
||||
class IFriends *m_pFriends;
|
||||
|
|
|
@ -206,7 +206,7 @@ int CSound::Init()
|
|||
|
||||
m_SoundLock = lock_create();
|
||||
|
||||
if(!g_Config.m_SndEnable)
|
||||
if(!g_Config.m_SndInit)
|
||||
return 0;
|
||||
|
||||
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
|
||||
|
|
|
@ -67,6 +67,11 @@ public:
|
|||
CFontSizeData m_aSizes[NUM_FONT_SIZES];
|
||||
};
|
||||
|
||||
struct CQuadChar
|
||||
{
|
||||
float m_aUvs[4];
|
||||
IGraphics::CQuadItem m_QuadItem;
|
||||
};
|
||||
|
||||
class CTextRender : public IEngineTextRender
|
||||
{
|
||||
|
@ -165,7 +170,7 @@ class CTextRender : public IEngineTextRender
|
|||
pSizeData->m_TextureWidth = Width;
|
||||
pSizeData->m_TextureHeight = Height;
|
||||
pSizeData->m_CurrentCharacter = 0;
|
||||
|
||||
|
||||
dbg_msg("", "pFont memory usage: %d", FontMemoryUsage);
|
||||
|
||||
mem_free(pMem);
|
||||
|
@ -538,6 +543,227 @@ public:
|
|||
m_TextOutlineA = a;
|
||||
}
|
||||
|
||||
virtual void TextShadowed(CTextCursor *pCursor, const char *pText, int Length, vec2 ShadowOffset,
|
||||
vec4 ShadowColor, vec4 TextColor_)
|
||||
{
|
||||
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||
float FakeToScreenX, FakeToScreenY;
|
||||
|
||||
// to correct coords, convert to screen coords, round, and convert back
|
||||
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||
|
||||
FakeToScreenX = (Graphics()->ScreenWidth()/(ScreenX1-ScreenX0));
|
||||
FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0));
|
||||
ShadowOffset.x /= FakeToScreenX;
|
||||
ShadowOffset.y /= FakeToScreenY;
|
||||
|
||||
CQuadChar aTextQuads[1024];
|
||||
int TextQuadCount = 0;
|
||||
IGraphics::CTextureHandle FontTexture;
|
||||
|
||||
TextDeferredRenderEx(pCursor, pText, Length, aTextQuads, sizeof(aTextQuads)/sizeof(aTextQuads[0]),
|
||||
&TextQuadCount, &FontTexture);
|
||||
|
||||
Graphics()->TextureSet(FontTexture);
|
||||
|
||||
Graphics()->QuadsBegin();
|
||||
|
||||
// shadow pass
|
||||
Graphics()->SetColor(ShadowColor.r, ShadowColor.g, ShadowColor.b, ShadowColor.a);
|
||||
|
||||
for(int i = 0; i < TextQuadCount; i++)
|
||||
{
|
||||
const CQuadChar& q = aTextQuads[i];
|
||||
Graphics()->QuadsSetSubset(q.m_aUvs[0], q.m_aUvs[1], q.m_aUvs[2], q.m_aUvs[3]);
|
||||
|
||||
IGraphics::CQuadItem QuadItem = q.m_QuadItem;
|
||||
QuadItem.m_X += ShadowOffset.x;
|
||||
QuadItem.m_Y += ShadowOffset.y;
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
}
|
||||
|
||||
// text pass
|
||||
Graphics()->SetColor(TextColor_.r, TextColor_.g, TextColor_.b, TextColor_.a);
|
||||
|
||||
for(int i = 0; i < TextQuadCount; i++)
|
||||
{
|
||||
const CQuadChar& q = aTextQuads[i];
|
||||
Graphics()->QuadsSetSubset(q.m_aUvs[0], q.m_aUvs[1], q.m_aUvs[2], q.m_aUvs[3]);
|
||||
Graphics()->QuadsDrawTL(&q.m_QuadItem, 1);
|
||||
}
|
||||
|
||||
Graphics()->QuadsEnd();
|
||||
}
|
||||
|
||||
virtual void TextDeferredRenderEx(CTextCursor *pCursor, const char *pText, int Length,
|
||||
CQuadChar* aQuadChar, int QuadCharMaxCount, int* pQuadCharCount,
|
||||
IGraphics::CTextureHandle* pFontTexture)
|
||||
{
|
||||
CFont *pFont = pCursor->m_pFont;
|
||||
CFontSizeData *pSizeData = NULL;
|
||||
|
||||
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||
float FakeToScreenX, FakeToScreenY;
|
||||
int ActualX, ActualY;
|
||||
|
||||
int ActualSize;
|
||||
int GotNewLine = 0;
|
||||
float DrawX = 0.0f, DrawY = 0.0f;
|
||||
int LineCount = 0;
|
||||
float CursorX, CursorY;
|
||||
|
||||
float Size = pCursor->m_FontSize;
|
||||
|
||||
// to correct coords, convert to screen coords, round, and convert back
|
||||
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||
|
||||
FakeToScreenX = (Graphics()->ScreenWidth()/(ScreenX1-ScreenX0));
|
||||
FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0));
|
||||
ActualX = (int)(pCursor->m_X * FakeToScreenX);
|
||||
ActualY = (int)(pCursor->m_Y * FakeToScreenY);
|
||||
|
||||
CursorX = ActualX / FakeToScreenX;
|
||||
CursorY = ActualY / FakeToScreenY;
|
||||
|
||||
// same with size
|
||||
ActualSize = (int)(Size * FakeToScreenY);
|
||||
Size = ActualSize / FakeToScreenY;
|
||||
|
||||
// fetch pFont data
|
||||
if(!pFont)
|
||||
pFont = m_pDefaultFont;
|
||||
|
||||
if(!pFont)
|
||||
return;
|
||||
|
||||
pSizeData = GetSize(pFont, ActualSize);
|
||||
RenderSetup(pFont, ActualSize);
|
||||
*pFontTexture = pSizeData->m_aTextures[0];
|
||||
|
||||
float Scale = 1.0f/pSizeData->m_FontSize;
|
||||
|
||||
// set length
|
||||
if(Length < 0)
|
||||
Length = str_length(pText);
|
||||
|
||||
|
||||
const char *pCurrent = (char *)pText;
|
||||
const char *pEnd = pCurrent+Length;
|
||||
DrawX = CursorX;
|
||||
DrawY = CursorY;
|
||||
LineCount = pCursor->m_LineCount;
|
||||
|
||||
while(pCurrent < pEnd && (pCursor->m_MaxLines < 1 || LineCount <= pCursor->m_MaxLines))
|
||||
{
|
||||
int NewLine = 0;
|
||||
const char *pBatchEnd = pEnd;
|
||||
if(pCursor->m_LineWidth > 0 && !(pCursor->m_Flags&TEXTFLAG_STOP_AT_END))
|
||||
{
|
||||
int Wlen = min(WordLength((char *)pCurrent), (int)(pEnd-pCurrent));
|
||||
CTextCursor Compare = *pCursor;
|
||||
Compare.m_X = DrawX;
|
||||
Compare.m_Y = DrawY;
|
||||
Compare.m_Flags &= ~TEXTFLAG_RENDER;
|
||||
Compare.m_LineWidth = -1;
|
||||
TextDeferredRenderEx(&Compare, pCurrent, Wlen, aQuadChar, QuadCharMaxCount, pQuadCharCount,
|
||||
pFontTexture);
|
||||
|
||||
if(Compare.m_X-DrawX > pCursor->m_LineWidth)
|
||||
{
|
||||
// word can't be fitted in one line, cut it
|
||||
CTextCursor Cutter = *pCursor;
|
||||
Cutter.m_CharCount = 0;
|
||||
Cutter.m_X = DrawX;
|
||||
Cutter.m_Y = DrawY;
|
||||
Cutter.m_Flags &= ~TEXTFLAG_RENDER;
|
||||
Cutter.m_Flags |= TEXTFLAG_STOP_AT_END;
|
||||
|
||||
TextDeferredRenderEx(&Cutter, (const char *)pCurrent, Wlen, aQuadChar, QuadCharMaxCount,
|
||||
pQuadCharCount, pFontTexture);
|
||||
Wlen = Cutter.m_CharCount;
|
||||
NewLine = 1;
|
||||
|
||||
if(Wlen <= 3) // if we can't place 3 chars of the word on this line, take the next
|
||||
Wlen = 0;
|
||||
}
|
||||
else if(Compare.m_X-pCursor->m_StartX > pCursor->m_LineWidth)
|
||||
{
|
||||
NewLine = 1;
|
||||
Wlen = 0;
|
||||
}
|
||||
|
||||
pBatchEnd = pCurrent + Wlen;
|
||||
}
|
||||
|
||||
const char *pTmp = pCurrent;
|
||||
int NextCharacter = str_utf8_decode(&pTmp);
|
||||
while(pCurrent < pBatchEnd)
|
||||
{
|
||||
int Character = NextCharacter;
|
||||
pCurrent = pTmp;
|
||||
NextCharacter = str_utf8_decode(&pTmp);
|
||||
|
||||
if(Character == '\n')
|
||||
{
|
||||
DrawX = pCursor->m_StartX;
|
||||
DrawY += Size;
|
||||
DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign
|
||||
DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY;
|
||||
++LineCount;
|
||||
if(pCursor->m_MaxLines > 0 && LineCount > pCursor->m_MaxLines)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
CFontChar *pChr = GetChar(pFont, pSizeData, Character);
|
||||
if(pChr)
|
||||
{
|
||||
float Advance = pChr->m_AdvanceX + Kerning(pFont, Character, NextCharacter)*Scale;
|
||||
if(pCursor->m_Flags&TEXTFLAG_STOP_AT_END && DrawX+Advance*Size-pCursor->m_StartX > pCursor->m_LineWidth)
|
||||
{
|
||||
// we hit the end of the line, no more to render or count
|
||||
pCurrent = pEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
if(pCursor->m_Flags&TEXTFLAG_RENDER)
|
||||
{
|
||||
dbg_assert(*pQuadCharCount < QuadCharMaxCount, "aQuadChar size is too small");
|
||||
|
||||
CQuadChar QuadChar;
|
||||
memmove(QuadChar.m_aUvs, pChr->m_aUvs, sizeof(pChr->m_aUvs));
|
||||
|
||||
IGraphics::CQuadItem QuadItem(DrawX+pChr->m_OffsetX*Size,
|
||||
DrawY+pChr->m_OffsetY*Size,
|
||||
pChr->m_Width*Size,
|
||||
pChr->m_Height*Size);
|
||||
QuadChar.m_QuadItem = QuadItem;
|
||||
aQuadChar[(*pQuadCharCount)++] = QuadChar;
|
||||
}
|
||||
|
||||
DrawX += Advance*Size;
|
||||
pCursor->m_CharCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(NewLine)
|
||||
{
|
||||
DrawX = pCursor->m_StartX;
|
||||
DrawY += Size;
|
||||
GotNewLine = 1;
|
||||
DrawX = (int)(DrawX * FakeToScreenX) / FakeToScreenX; // realign
|
||||
DrawY = (int)(DrawY * FakeToScreenY) / FakeToScreenY;
|
||||
++LineCount;
|
||||
}
|
||||
}
|
||||
|
||||
pCursor->m_X = DrawX;
|
||||
pCursor->m_LineCount = LineCount;
|
||||
|
||||
if(GotNewLine)
|
||||
pCursor->m_Y = DrawY;
|
||||
}
|
||||
|
||||
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length)
|
||||
{
|
||||
CFont *pFont = pCursor->m_pFont;
|
||||
|
@ -722,6 +948,38 @@ public:
|
|||
pCursor->m_Y = DrawY;
|
||||
}
|
||||
|
||||
float TextGetLineBaseY(const CTextCursor *pCursor)
|
||||
{
|
||||
CFont *pFont = pCursor->m_pFont;
|
||||
CFontSizeData *pSizeData = NULL;
|
||||
|
||||
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||
float Size = pCursor->m_FontSize;
|
||||
|
||||
// to correct coords, convert to screen coords, round, and convert back
|
||||
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||
|
||||
float FakeToScreenY = (Graphics()->ScreenHeight()/(ScreenY1-ScreenY0));
|
||||
int ActualY = (int)(pCursor->m_Y * FakeToScreenY);
|
||||
float CursorY = ActualY / FakeToScreenY;
|
||||
|
||||
// same with size
|
||||
int ActualSize = (int)(Size * FakeToScreenY);
|
||||
Size = ActualSize / FakeToScreenY;
|
||||
|
||||
// fetch pFont data
|
||||
if(!pFont)
|
||||
pFont = m_pDefaultFont;
|
||||
|
||||
if(!pFont)
|
||||
return 0;
|
||||
|
||||
pSizeData = GetSize(pFont, ActualSize);
|
||||
RenderSetup(pFont, ActualSize);
|
||||
CFontChar *pChr = GetChar(pFont, pSizeData, ' ');
|
||||
return CursorY + pChr->m_OffsetY*Size + pChr->m_Height*Size;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
IEngineTextRender *CreateEngineTextRender() { return new CTextRender; }
|
||||
|
|
2
src/engine/external/json-parser/VERSION
vendored
|
@ -1 +1 @@
|
|||
unmarked version: 17.12.2012
|
||||
unmarked version: 11.11.2018
|
||||
|
|
424
src/engine/external/json-parser/json.c
vendored
|
@ -1,7 +1,6 @@
|
|||
|
||||
/* vim: set et ts=3 sw=3 ft=c:
|
||||
/* vim: set et ts=3 sw=3 sts=3 ft=c:
|
||||
*
|
||||
* Copyright (C) 2012 James McLaughlin et al. All rights reserved.
|
||||
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
|
||||
* https://github.com/udp/json-parser
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -36,50 +35,58 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
const struct _json_value json_value_none; /* zero-d by ctor */
|
||||
#else
|
||||
const struct _json_value json_value_none = { 0 };
|
||||
#endif
|
||||
const struct _json_value json_value_none;
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef unsigned short json_uchar;
|
||||
typedef unsigned int json_uchar;
|
||||
|
||||
static unsigned char hex_value (json_char c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return (c - 'A') + 10;
|
||||
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return (c - 'a') + 10;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
if (isdigit(c))
|
||||
return c - '0';
|
||||
|
||||
return 0xFF;
|
||||
switch (c) {
|
||||
case 'a': case 'A': return 0x0A;
|
||||
case 'b': case 'B': return 0x0B;
|
||||
case 'c': case 'C': return 0x0C;
|
||||
case 'd': case 'D': return 0x0D;
|
||||
case 'e': case 'E': return 0x0E;
|
||||
case 'f': case 'F': return 0x0F;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
json_settings settings;
|
||||
int first_pass;
|
||||
|
||||
unsigned long used_memory;
|
||||
|
||||
unsigned int uint_max;
|
||||
unsigned long ulong_max;
|
||||
|
||||
json_settings settings;
|
||||
int first_pass;
|
||||
|
||||
const json_char * ptr;
|
||||
unsigned int cur_line, cur_col;
|
||||
|
||||
} json_state;
|
||||
|
||||
static void * default_alloc (size_t size, int zero, void * user_data)
|
||||
{
|
||||
return zero ? calloc (1, size) : malloc (size);
|
||||
}
|
||||
|
||||
static void default_free (void * ptr, void * user_data)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
static void * json_alloc (json_state * state, unsigned long size, int zero)
|
||||
{
|
||||
void * mem;
|
||||
|
||||
if ((state->ulong_max - state->used_memory) < size)
|
||||
return 0;
|
||||
|
||||
|
@ -89,14 +96,12 @@ static void * json_alloc (json_state * state, unsigned long size, int zero)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (! (mem = zero ? calloc (size, 1) : malloc (size)))
|
||||
return 0;
|
||||
|
||||
return mem;
|
||||
return state->settings.mem_alloc (size, zero, state->settings.user_data);
|
||||
}
|
||||
|
||||
static int new_value
|
||||
(json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type)
|
||||
static int new_value (json_state * state,
|
||||
json_value ** top, json_value ** root, json_value ** alloc,
|
||||
json_type type)
|
||||
{
|
||||
json_value * value;
|
||||
int values_size;
|
||||
|
@ -113,6 +118,9 @@ static int new_value
|
|||
{
|
||||
case json_array:
|
||||
|
||||
if (value->u.array.length == 0)
|
||||
break;
|
||||
|
||||
if (! (value->u.array.values = (json_value **) json_alloc
|
||||
(state, value->u.array.length * sizeof (json_value *), 0)) )
|
||||
{
|
||||
|
@ -124,9 +132,12 @@ static int new_value
|
|||
|
||||
case json_object:
|
||||
|
||||
if (value->u.object.length == 0)
|
||||
break;
|
||||
|
||||
values_size = sizeof (*value->u.object.values) * value->u.object.length;
|
||||
|
||||
if (! ((*(void **) &value->u.object.values) = json_alloc
|
||||
if (! (value->u.object.values = (json_object_entry *) json_alloc
|
||||
(state, values_size + ((unsigned long) value->u.object.values), 0)) )
|
||||
{
|
||||
return 0;
|
||||
|
@ -155,10 +166,11 @@ static int new_value
|
|||
return 1;
|
||||
}
|
||||
|
||||
value = (json_value *) json_alloc (state, sizeof (json_value), 1);
|
||||
|
||||
if (!value)
|
||||
if (! (value = (json_value *) json_alloc
|
||||
(state, sizeof (json_value) + state->settings.value_extra, 1)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!*root)
|
||||
*root = value;
|
||||
|
@ -166,6 +178,11 @@ static int new_value
|
|||
value->type = type;
|
||||
value->parent = *top;
|
||||
|
||||
#ifdef JSON_TRACK_SOURCE
|
||||
value->line = state->cur_line;
|
||||
value->col = state->cur_col;
|
||||
#endif
|
||||
|
||||
if (*alloc)
|
||||
(*alloc)->_reserved.next_alloc = value;
|
||||
|
||||
|
@ -174,38 +191,67 @@ static int new_value
|
|||
return 1;
|
||||
}
|
||||
|
||||
#define e_off \
|
||||
((int) (i - cur_line_begin))
|
||||
|
||||
#define whitespace \
|
||||
case '\n': ++ cur_line; cur_line_begin = i; \
|
||||
case '\n': ++ state.cur_line; state.cur_col = 0; \
|
||||
case ' ': case '\t': case '\r'
|
||||
|
||||
#define string_add(b) \
|
||||
do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
|
||||
|
||||
const static long
|
||||
flag_next = 1, flag_reproc = 2, flag_need_comma = 4, flag_seek_value = 8,
|
||||
flag_escaped = 16, flag_string = 32, flag_need_colon = 64, flag_done = 128,
|
||||
flag_num_negative = 256, flag_num_zero = 512, flag_num_e = 1024,
|
||||
flag_num_e_got_sign = 2048, flag_num_e_negative = 4096;
|
||||
#define line_and_col \
|
||||
state.cur_line, state.cur_col
|
||||
|
||||
json_value * json_parse_ex (json_settings * settings, const json_char * json, char * error_buf)
|
||||
static const long
|
||||
flag_next = 1 << 0,
|
||||
flag_reproc = 1 << 1,
|
||||
flag_need_comma = 1 << 2,
|
||||
flag_seek_value = 1 << 3,
|
||||
flag_escaped = 1 << 4,
|
||||
flag_string = 1 << 5,
|
||||
flag_need_colon = 1 << 6,
|
||||
flag_done = 1 << 7,
|
||||
flag_num_negative = 1 << 8,
|
||||
flag_num_zero = 1 << 9,
|
||||
flag_num_e = 1 << 10,
|
||||
flag_num_e_got_sign = 1 << 11,
|
||||
flag_num_e_negative = 1 << 12,
|
||||
flag_line_comment = 1 << 13,
|
||||
flag_block_comment = 1 << 14;
|
||||
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error_buf)
|
||||
{
|
||||
json_char error [128];
|
||||
unsigned int cur_line;
|
||||
const json_char * cur_line_begin, * i;
|
||||
json_char error [json_error_max];
|
||||
const json_char * end;
|
||||
json_value * top, * root, * alloc = 0;
|
||||
json_state state;
|
||||
json_state state = { 0 };
|
||||
long flags;
|
||||
long num_digits, num_fraction, num_e;
|
||||
long num_digits = 0, num_e = 0;
|
||||
json_int_t num_fraction = 0;
|
||||
|
||||
/* Skip UTF-8 BOM
|
||||
*/
|
||||
if (length >= 3 && ((unsigned char) json [0]) == 0xEF
|
||||
&& ((unsigned char) json [1]) == 0xBB
|
||||
&& ((unsigned char) json [2]) == 0xBF)
|
||||
{
|
||||
json += 3;
|
||||
length -= 3;
|
||||
}
|
||||
|
||||
error[0] = '\0';
|
||||
num_digits = num_fraction = num_e = 0;
|
||||
end = (json + length);
|
||||
|
||||
memset (&state, 0, sizeof (json_state));
|
||||
memcpy (&state.settings, settings, sizeof (json_settings));
|
||||
|
||||
if (!state.settings.mem_alloc)
|
||||
state.settings.mem_alloc = default_alloc;
|
||||
|
||||
if (!state.settings.mem_free)
|
||||
state.settings.mem_free = default_free;
|
||||
|
||||
memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
|
||||
memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
|
||||
|
||||
|
@ -216,41 +262,22 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
{
|
||||
json_uchar uchar;
|
||||
unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
|
||||
json_char * string;
|
||||
unsigned int string_length;
|
||||
json_char * string = 0;
|
||||
unsigned int string_length = 0;
|
||||
|
||||
top = root = 0;
|
||||
flags = flag_seek_value;
|
||||
string_length = 0;
|
||||
string = 0;
|
||||
|
||||
cur_line = 1;
|
||||
cur_line_begin = json;
|
||||
state.cur_line = 1;
|
||||
|
||||
for (i = json ;; ++ i)
|
||||
for (state.ptr = json ;; ++ state.ptr)
|
||||
{
|
||||
json_char b = *i;
|
||||
|
||||
if (flags & flag_done)
|
||||
{
|
||||
if (!b)
|
||||
break;
|
||||
|
||||
switch (b)
|
||||
{
|
||||
whitespace:
|
||||
continue;
|
||||
|
||||
default:
|
||||
sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
|
||||
goto e_failed;
|
||||
};
|
||||
}
|
||||
|
||||
json_char b = (state.ptr == end ? 0 : *state.ptr);
|
||||
|
||||
if (flags & flag_string)
|
||||
{
|
||||
if (!b)
|
||||
{ sprintf (error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off);
|
||||
{ sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
|
@ -270,19 +297,41 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
case 't': string_add ('\t'); break;
|
||||
case 'u':
|
||||
|
||||
if ((uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
|
||||
|| (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF)
|
||||
if (end - state.ptr <= 4 ||
|
||||
(uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
||||
{
|
||||
sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off);
|
||||
sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
uc_b1 = uc_b1 * 16 + uc_b2;
|
||||
uc_b2 = uc_b3 * 16 + uc_b4;
|
||||
uc_b1 = (uc_b1 << 4) | uc_b2;
|
||||
uc_b2 = (uc_b3 << 4) | uc_b4;
|
||||
uchar = (uc_b1 << 8) | uc_b2;
|
||||
|
||||
uchar = ((json_char) uc_b1) * 256 + uc_b2;
|
||||
if ((uchar & 0xF800) == 0xD800) {
|
||||
json_uchar uchar2;
|
||||
|
||||
if (end - state.ptr <= 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
|
||||
(uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
||||
{
|
||||
sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (sizeof (json_char) >= sizeof (json_uchar) || (uc_b1 == 0 && uc_b2 <= 0x7F))
|
||||
uc_b1 = (uc_b1 << 4) | uc_b2;
|
||||
uc_b2 = (uc_b3 << 4) | uc_b4;
|
||||
uchar2 = (uc_b1 << 8) | uc_b2;
|
||||
|
||||
uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
|
||||
}
|
||||
|
||||
if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
|
||||
{
|
||||
string_add ((json_char) uchar);
|
||||
break;
|
||||
|
@ -293,19 +342,32 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
if (state.first_pass)
|
||||
string_length += 2;
|
||||
else
|
||||
{ string [string_length ++] = 0xC0 | ((uc_b2 & 0xC0) >> 6) | ((uc_b1 & 0x7) << 2);
|
||||
string [string_length ++] = 0x80 | (uc_b2 & 0x3F);
|
||||
{ string [string_length ++] = 0xC0 | (uchar >> 6);
|
||||
string [string_length ++] = 0x80 | (uchar & 0x3F);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (uchar <= 0xFFFF) {
|
||||
if (state.first_pass)
|
||||
string_length += 3;
|
||||
else
|
||||
{ string [string_length ++] = 0xE0 | (uchar >> 12);
|
||||
string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
|
||||
string [string_length ++] = 0x80 | (uchar & 0x3F);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (state.first_pass)
|
||||
string_length += 3;
|
||||
string_length += 4;
|
||||
else
|
||||
{ string [string_length ++] = 0xE0 | ((uc_b1 & 0xF0) >> 4);
|
||||
string [string_length ++] = 0x80 | ((uc_b1 & 0xF) << 2) | ((uc_b2 & 0xC0) >> 6);
|
||||
string [string_length ++] = 0x80 | (uc_b2 & 0x3F);
|
||||
{ string [string_length ++] = 0xF0 | (uchar >> 18);
|
||||
string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
|
||||
string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
|
||||
string [string_length ++] = 0x80 | (uchar & 0x3F);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -349,6 +411,9 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
top->u.object.values [top->u.object.length].name
|
||||
= (json_char *) top->_reserved.object_mem;
|
||||
|
||||
top->u.object.values [top->u.object.length].name_length
|
||||
= string_length;
|
||||
|
||||
(*(json_char **) &top->_reserved.object_mem) += string_length + 1;
|
||||
}
|
||||
|
||||
|
@ -366,6 +431,85 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
}
|
||||
}
|
||||
|
||||
if (state.settings.settings & json_enable_comments)
|
||||
{
|
||||
if (flags & (flag_line_comment | flag_block_comment))
|
||||
{
|
||||
if (flags & flag_line_comment)
|
||||
{
|
||||
if (b == '\r' || b == '\n' || !b)
|
||||
{
|
||||
flags &= ~ flag_line_comment;
|
||||
-- state.ptr; /* so null can be reproc'd */
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & flag_block_comment)
|
||||
{
|
||||
if (!b)
|
||||
{ sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')
|
||||
{
|
||||
flags &= ~ flag_block_comment;
|
||||
++ state.ptr; /* skip closing sequence */
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (b == '/')
|
||||
{
|
||||
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
|
||||
{ sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (++ state.ptr == end)
|
||||
{ sprintf (error, "%d:%d: EOF unexpected", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
switch (b = *state.ptr)
|
||||
{
|
||||
case '/':
|
||||
flags |= flag_line_comment;
|
||||
continue;
|
||||
|
||||
case '*':
|
||||
flags |= flag_block_comment;
|
||||
continue;
|
||||
|
||||
default:
|
||||
sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
|
||||
goto e_failed;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & flag_done)
|
||||
{
|
||||
if (!b)
|
||||
break;
|
||||
|
||||
switch (b)
|
||||
{
|
||||
whitespace:
|
||||
continue;
|
||||
|
||||
default:
|
||||
|
||||
sprintf (error, "%d:%d: Trailing garbage: `%c`",
|
||||
state.cur_line, state.cur_col, b);
|
||||
|
||||
goto e_failed;
|
||||
};
|
||||
}
|
||||
|
||||
if (flags & flag_seek_value)
|
||||
{
|
||||
switch (b)
|
||||
|
@ -375,10 +519,10 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
|
||||
case ']':
|
||||
|
||||
if (top->type == json_array)
|
||||
if (top && top->type == json_array)
|
||||
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
|
||||
else if (!state.settings.settings & json_relaxed_commas)
|
||||
{ sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off);
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Unexpected ]", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
|
@ -393,7 +537,10 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
continue;
|
||||
}
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Expected , before %c", cur_line, e_off, b);
|
||||
{
|
||||
sprintf (error, "%d:%d: Expected , before %c",
|
||||
state.cur_line, state.cur_col, b);
|
||||
|
||||
goto e_failed;
|
||||
}
|
||||
}
|
||||
|
@ -405,7 +552,10 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
continue;
|
||||
}
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Expected : before %c", cur_line, e_off, b);
|
||||
{
|
||||
sprintf (error, "%d:%d: Expected : before %c",
|
||||
state.cur_line, state.cur_col, b);
|
||||
|
||||
goto e_failed;
|
||||
}
|
||||
}
|
||||
|
@ -443,8 +593,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
|
||||
case 't':
|
||||
|
||||
if (*(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e')
|
||||
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
|
||||
*(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
|
||||
{
|
||||
goto e_unknown_value;
|
||||
}
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_boolean))
|
||||
goto e_alloc_failure;
|
||||
|
@ -456,8 +609,12 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
|
||||
case 'f':
|
||||
|
||||
if (*(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e')
|
||||
if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
|
||||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
|
||||
*(++ state.ptr) != 'e')
|
||||
{
|
||||
goto e_unknown_value;
|
||||
}
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_boolean))
|
||||
goto e_alloc_failure;
|
||||
|
@ -467,8 +624,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
|
||||
case 'n':
|
||||
|
||||
if (*(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l')
|
||||
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
|
||||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
|
||||
{
|
||||
goto e_unknown_value;
|
||||
}
|
||||
|
||||
if (!new_value (&state, &top, &root, &alloc, json_null))
|
||||
goto e_alloc_failure;
|
||||
|
@ -488,7 +648,13 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
while (isdigit (b) || b == '+' || b == '-'
|
||||
|| b == 'e' || b == 'E' || b == '.')
|
||||
{
|
||||
b = *++ i;
|
||||
if ( (++ state.ptr) == end)
|
||||
{
|
||||
b = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
b = *state.ptr;
|
||||
}
|
||||
|
||||
flags |= flag_next | flag_reproc;
|
||||
|
@ -513,7 +679,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
continue;
|
||||
}
|
||||
else
|
||||
{ sprintf (error, "%d:%d: Unexpected %c when seeking value", cur_line, e_off, b);
|
||||
{ sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
|
||||
goto e_failed;
|
||||
}
|
||||
};
|
||||
|
@ -532,9 +698,8 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
|
||||
case '"':
|
||||
|
||||
if (flags & flag_need_comma && (!state.settings.settings & json_relaxed_commas))
|
||||
{
|
||||
sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off);
|
||||
if (flags & flag_need_comma)
|
||||
{ sprintf (error, "%d:%d: Expected , before \"", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
|
@ -559,8 +724,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
}
|
||||
|
||||
default:
|
||||
|
||||
sprintf (error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b);
|
||||
sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
|
||||
goto e_failed;
|
||||
};
|
||||
|
||||
|
@ -578,7 +742,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
if (! (flags & flag_num_e))
|
||||
{
|
||||
if (flags & flag_num_zero)
|
||||
{ sprintf (error, "%d:%d: Unexpected `0` before `%c`", cur_line, e_off, b);
|
||||
{ sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
|
@ -615,12 +779,12 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
else if (b == '.' && top->type == json_integer)
|
||||
{
|
||||
if (!num_digits)
|
||||
{ sprintf (error, "%d:%d: Expected digit before `.`", cur_line, e_off);
|
||||
{ sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
top->type = json_double;
|
||||
top->u.dbl = top->u.integer;
|
||||
top->u.dbl = (double) top->u.integer;
|
||||
|
||||
num_digits = 0;
|
||||
continue;
|
||||
|
@ -631,11 +795,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
if (top->type == json_double)
|
||||
{
|
||||
if (!num_digits)
|
||||
{ sprintf (error, "%d:%d: Expected digit after `.`", cur_line, e_off);
|
||||
{ sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
top->u.dbl += ((double) num_fraction) / (pow (10, num_digits));
|
||||
top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits));
|
||||
}
|
||||
|
||||
if (b == 'e' || b == 'E')
|
||||
|
@ -645,7 +809,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
if (top->type == json_integer)
|
||||
{
|
||||
top->type = json_double;
|
||||
top->u.dbl = top->u.integer;
|
||||
top->u.dbl = (double) top->u.integer;
|
||||
}
|
||||
|
||||
num_digits = 0;
|
||||
|
@ -657,11 +821,12 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
else
|
||||
{
|
||||
if (!num_digits)
|
||||
{ sprintf (error, "%d:%d: Expected digit after `e`", cur_line, e_off);
|
||||
{ sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
top->u.dbl *= pow (10, flags & flag_num_e_negative ? - num_e : num_e);
|
||||
top->u.dbl *= pow (10.0, (double)
|
||||
(flags & flag_num_e_negative ? - num_e : num_e));
|
||||
}
|
||||
|
||||
if (flags & flag_num_negative)
|
||||
|
@ -683,7 +848,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
if (flags & flag_reproc)
|
||||
{
|
||||
flags &= ~ flag_reproc;
|
||||
-- i;
|
||||
-- state.ptr;
|
||||
}
|
||||
|
||||
if (flags & flag_next)
|
||||
|
@ -742,7 +907,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
|
|||
|
||||
e_unknown_value:
|
||||
|
||||
sprintf (error, "%d:%d: Unknown value", cur_line, e_off);
|
||||
sprintf (error, "%d:%d: Unknown value", line_and_col);
|
||||
goto e_failed;
|
||||
|
||||
e_alloc_failure:
|
||||
|
@ -752,7 +917,7 @@ e_alloc_failure:
|
|||
|
||||
e_overflow:
|
||||
|
||||
sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off);
|
||||
sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
|
||||
goto e_failed;
|
||||
|
||||
e_failed:
|
||||
|
@ -771,25 +936,23 @@ e_failed:
|
|||
while (alloc)
|
||||
{
|
||||
top = alloc->_reserved.next_alloc;
|
||||
free (alloc);
|
||||
state.settings.mem_free (alloc, state.settings.user_data);
|
||||
alloc = top;
|
||||
}
|
||||
|
||||
if (!state.first_pass)
|
||||
json_value_free (root);
|
||||
json_value_free_ex (&state.settings, root);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
json_value * json_parse (const json_char * json)
|
||||
json_value * json_parse (const json_char * json, size_t length)
|
||||
{
|
||||
json_settings settings;
|
||||
memset (&settings, 0, sizeof (json_settings));
|
||||
|
||||
return json_parse_ex (&settings, json, 0);
|
||||
json_settings settings = { 0 };
|
||||
return json_parse_ex (&settings, json, length, 0);
|
||||
}
|
||||
|
||||
void json_value_free (json_value * value)
|
||||
void json_value_free_ex (json_settings * settings, json_value * value)
|
||||
{
|
||||
json_value * cur_value;
|
||||
|
||||
|
@ -806,7 +969,7 @@ void json_value_free (json_value * value)
|
|||
|
||||
if (!value->u.array.length)
|
||||
{
|
||||
free (value->u.array.values);
|
||||
settings->mem_free (value->u.array.values, settings->user_data);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -817,7 +980,7 @@ void json_value_free (json_value * value)
|
|||
|
||||
if (!value->u.object.length)
|
||||
{
|
||||
free (value->u.object.values);
|
||||
settings->mem_free (value->u.object.values, settings->user_data);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -826,7 +989,7 @@ void json_value_free (json_value * value)
|
|||
|
||||
case json_string:
|
||||
|
||||
free (value->u.string.ptr);
|
||||
settings->mem_free (value->u.string.ptr, settings->user_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -835,7 +998,14 @@ void json_value_free (json_value * value)
|
|||
|
||||
cur_value = value;
|
||||
value = value->parent;
|
||||
free (cur_value);
|
||||
settings->mem_free (cur_value, settings->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
void json_value_free (json_value * value)
|
||||
{
|
||||
json_settings settings = { 0 };
|
||||
settings.mem_free = default_free;
|
||||
json_value_free_ex (&settings, value);
|
||||
}
|
||||
|
||||
|
|
125
src/engine/external/json-parser/json.h
vendored
|
@ -1,7 +1,7 @@
|
|||
|
||||
/* vim: set et ts=3 sw=3 ft=c:
|
||||
/* vim: set et ts=3 sw=3 sts=3 ft=c:
|
||||
*
|
||||
* Copyright (C) 2012 James McLaughlin et al. All rights reserved.
|
||||
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
|
||||
* https://github.com/udp/json-parser
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -35,6 +35,17 @@
|
|||
#define json_char char
|
||||
#endif
|
||||
|
||||
#ifndef json_int_t
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#define json_int_t int64_t
|
||||
#else
|
||||
#define json_int_t __int64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string.h>
|
||||
|
@ -49,9 +60,19 @@ typedef struct
|
|||
unsigned long max_memory;
|
||||
int settings;
|
||||
|
||||
/* Custom allocator support (leave null to use malloc/free)
|
||||
*/
|
||||
|
||||
void * (* mem_alloc) (size_t, int zero, void * user_data);
|
||||
void (* mem_free) (void *, void * user_data);
|
||||
|
||||
void * user_data; /* will be passed to mem_alloc and mem_free */
|
||||
|
||||
size_t value_extra; /* how much extra space to allocate for values? */
|
||||
|
||||
} json_settings;
|
||||
|
||||
#define json_relaxed_commas 1
|
||||
#define json_enable_comments 0x01
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -67,6 +88,15 @@ typedef enum
|
|||
} json_type;
|
||||
|
||||
extern const struct _json_value json_value_none;
|
||||
|
||||
typedef struct _json_object_entry
|
||||
{
|
||||
json_char * name;
|
||||
unsigned int name_length;
|
||||
|
||||
struct _json_value * value;
|
||||
|
||||
} json_object_entry;
|
||||
|
||||
typedef struct _json_value
|
||||
{
|
||||
|
@ -77,7 +107,7 @@ typedef struct _json_value
|
|||
union
|
||||
{
|
||||
int boolean;
|
||||
long integer;
|
||||
json_int_t integer;
|
||||
double dbl;
|
||||
|
||||
struct
|
||||
|
@ -91,12 +121,16 @@ typedef struct _json_value
|
|||
{
|
||||
unsigned int length;
|
||||
|
||||
struct
|
||||
{
|
||||
json_char * name;
|
||||
struct _json_value * value;
|
||||
json_object_entry * values;
|
||||
|
||||
} * values;
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} object;
|
||||
|
||||
|
@ -105,6 +139,15 @@ typedef struct _json_value
|
|||
unsigned int length;
|
||||
struct _json_value ** values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} array;
|
||||
|
||||
} u;
|
||||
|
@ -116,6 +159,14 @@ typedef struct _json_value
|
|||
|
||||
} _reserved;
|
||||
|
||||
#ifdef JSON_TRACK_SOURCE
|
||||
|
||||
/* Location of the value in the source JSON
|
||||
*/
|
||||
unsigned int line, col;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Some C++ operator sugar */
|
||||
|
||||
|
@ -162,27 +213,67 @@ typedef struct _json_value
|
|||
};
|
||||
}
|
||||
|
||||
inline operator long () const
|
||||
{ return u.integer;
|
||||
inline operator json_int_t () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return u.integer;
|
||||
|
||||
case json_double:
|
||||
return (json_int_t) u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
inline operator bool () const
|
||||
{ return u.boolean != 0;
|
||||
{
|
||||
if (type != json_boolean)
|
||||
return false;
|
||||
|
||||
return u.boolean != 0;
|
||||
}
|
||||
|
||||
inline operator double () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return (double) u.integer;
|
||||
|
||||
case json_double:
|
||||
return u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} json_value;
|
||||
|
||||
json_value * json_parse (const json_char * json,
|
||||
size_t length);
|
||||
|
||||
json_value * json_parse
|
||||
(const json_char * json);
|
||||
|
||||
json_value * json_parse_ex
|
||||
(json_settings * settings, const json_char * json, char * error);
|
||||
#define json_error_max 128
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error);
|
||||
|
||||
void json_value_free (json_value *);
|
||||
|
||||
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex (json_settings * settings,
|
||||
json_value *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
2
src/engine/external/zlib/VERSION
vendored
|
@ -1 +1 @@
|
|||
1.2.5
|
||||
1.2.11
|
||||
|
|
85
src/engine/external/zlib/adler32.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2007 Mark Adler
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -7,11 +7,9 @@
|
|||
|
||||
#include "zutil.h"
|
||||
|
||||
#define local static
|
||||
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
|
||||
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
|
||||
|
||||
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||
#define BASE 65521U /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
|
@ -21,46 +19,51 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
|
|||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware */
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware --
|
||||
try it both ways to see which is faster */
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
|
||||
(thank you to John Reiser for pointing this out) */
|
||||
# define CHOP(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
unsigned long tmp = a >> 16; \
|
||||
a &= 0xffffUL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
} while (0)
|
||||
# define MOD28(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD4(a) \
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
CHOP(a); \
|
||||
MOD28(a); \
|
||||
} while (0)
|
||||
# define MOD63(a) \
|
||||
do { /* this assumes a is not negative */ \
|
||||
z_off64_t tmp = a >> 32; \
|
||||
a &= 0xffffffffL; \
|
||||
a += (tmp << 8) - (tmp << 5) + tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD4(a) a %= BASE
|
||||
# define MOD28(a) a %= BASE
|
||||
# define MOD63(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong ZEXPORT adler32_z(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
z_size_t len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
|
@ -92,7 +95,7 @@ uLong ZEXPORT adler32(adler, buf, len)
|
|||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD4(sum2); /* only added so many BASE's */
|
||||
MOD28(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
|
@ -127,6 +130,15 @@ uLong ZEXPORT adler32(adler, buf, len)
|
|||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
return adler32_z(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong adler32_combine_(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
|
@ -137,8 +149,13 @@ local uLong adler32_combine_(adler1, adler2, len2)
|
|||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
||||
if (len2 < 0)
|
||||
return 0xffffffffUL;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
rem = (unsigned)(len2 % BASE);
|
||||
MOD63(len2); /* assumes len2 >= 0 */
|
||||
rem = (unsigned)len2;
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
|
@ -146,7 +163,7 @@ local uLong adler32_combine_(adler1, adler2, len2)
|
|||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
|
||||
if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
|
||||
if (sum2 >= BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
|
|
42
src/engine/external/zlib/compress.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -28,16 +28,11 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
|||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
const uInt max = (uInt)-1;
|
||||
uLong left;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
@ -46,15 +41,26 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
|||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = 0;
|
||||
stream.next_in = (z_const Bytef *)source;
|
||||
stream.avail_in = 0;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
do {
|
||||
if (stream.avail_out == 0) {
|
||||
stream.avail_out = left > (uLong)max ? max : (uInt)left;
|
||||
left -= stream.avail_out;
|
||||
}
|
||||
if (stream.avail_in == 0) {
|
||||
stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
|
||||
sourceLen -= stream.avail_in;
|
||||
}
|
||||
err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*destLen = stream.total_out;
|
||||
deflateEnd(&stream);
|
||||
return err == Z_STREAM_END ? Z_OK : err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
|
122
src/engine/external/zlib/crc32.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010 Mark Adler
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
|
@ -17,6 +17,8 @@
|
|||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
|
||||
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
|
@ -28,37 +30,15 @@
|
|||
|
||||
#include "zutil.h" /* for STDC and FAR definitions */
|
||||
|
||||
#define local static
|
||||
|
||||
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
|
||||
#ifndef NOBYFOUR
|
||||
# ifdef STDC /* need ANSI C limits.h to determine sizes */
|
||||
# include <limits.h>
|
||||
# define BYFOUR
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
typedef unsigned int u4;
|
||||
# else
|
||||
# if (ULONG_MAX == 0xffffffffUL)
|
||||
typedef unsigned long u4;
|
||||
# else
|
||||
# if (USHRT_MAX == 0xffffffffUL)
|
||||
typedef unsigned short u4;
|
||||
# else
|
||||
# undef BYFOUR /* can't find a four-byte integer type! */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif /* STDC */
|
||||
#endif /* !NOBYFOUR */
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#if !defined(NOBYFOUR) && defined(Z_U4)
|
||||
# define BYFOUR
|
||||
#endif
|
||||
#ifdef BYFOUR
|
||||
# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
|
||||
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
const unsigned char FAR *, z_size_t));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
const unsigned char FAR *, z_size_t));
|
||||
# define TBLS 8
|
||||
#else
|
||||
# define TBLS 1
|
||||
|
@ -68,16 +48,16 @@
|
|||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
|
||||
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
|
||||
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local unsigned long FAR crc_table[TBLS][256];
|
||||
local z_crc_t FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const unsigned long FAR *));
|
||||
local void write_table OF((FILE *, const z_crc_t FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
|
@ -107,9 +87,9 @@ local void make_crc_table OF((void));
|
|||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
unsigned long c;
|
||||
z_crc_t c;
|
||||
int n, k;
|
||||
unsigned long poly; /* polynomial exclusive-or pattern */
|
||||
z_crc_t poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
@ -121,13 +101,13 @@ local void make_crc_table()
|
|||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0UL;
|
||||
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
|
||||
poly |= 1UL << (31 - p[n]);
|
||||
poly = 0;
|
||||
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||
poly |= (z_crc_t)1 << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long)n;
|
||||
c = (z_crc_t)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
|
@ -138,11 +118,11 @@ local void make_crc_table()
|
|||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = REV(c);
|
||||
crc_table[4][n] = ZSWAP32(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = REV(c);
|
||||
crc_table[k + 4][n] = ZSWAP32(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
@ -164,7 +144,7 @@ local void make_crc_table()
|
|||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const unsigned long FAR ");
|
||||
fprintf(out, "local const z_crc_t FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
|
@ -184,12 +164,13 @@ local void make_crc_table()
|
|||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const unsigned long FAR *table;
|
||||
const z_crc_t FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
|
||||
(unsigned long)(table[n]),
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
@ -204,13 +185,13 @@ local void write_table(out, table)
|
|||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const unsigned long FAR * ZEXPORT get_crc_table()
|
||||
const z_crc_t FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const unsigned long FAR *)crc_table;
|
||||
return (const z_crc_t FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
@ -218,10 +199,10 @@ const unsigned long FAR * ZEXPORT get_crc_table()
|
|||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long ZEXPORT crc32_z(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
uInt len;
|
||||
z_size_t len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
|
@ -232,7 +213,7 @@ unsigned long ZEXPORT crc32(crc, buf, len)
|
|||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
u4 endian;
|
||||
z_crc_t endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
|
@ -252,8 +233,29 @@ unsigned long ZEXPORT crc32(crc, buf, len)
|
|||
return crc ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
uInt len;
|
||||
{
|
||||
return crc32_z(crc, buf, len);
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
|
||||
/*
|
||||
This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
|
||||
integer pointer type. This violates the strict aliasing rule, where a
|
||||
compiler can assume, for optimization purposes, that two pointers to
|
||||
fundamentally different types won't ever point to the same memory. This can
|
||||
manifest as a problem only if one of the pointers is written to. This code
|
||||
only reads from those pointers. So long as this code remains isolated in
|
||||
this compilation unit, there won't be a problem. For this reason, this code
|
||||
should not be copied and pasted into a compilation unit in which other code
|
||||
writes to the buffer that is passed to these routines.
|
||||
*/
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
|
@ -264,19 +266,19 @@ unsigned long ZEXPORT crc32(crc, buf, len)
|
|||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
z_size_t len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = (u4)crc;
|
||||
c = (z_crc_t)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
|
@ -295,7 +297,7 @@ local unsigned long crc32_little(crc, buf, len)
|
|||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOBIG4 c ^= *++buf4; \
|
||||
#define DOBIG4 c ^= *buf4++; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
@ -304,20 +306,19 @@ local unsigned long crc32_little(crc, buf, len)
|
|||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
z_size_t len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = REV((u4)crc);
|
||||
c = ZSWAP32((z_crc_t)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4--;
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
|
@ -326,14 +327,13 @@ local unsigned long crc32_big(crc, buf, len)
|
|||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf4++;
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(REV(c));
|
||||
return (unsigned long)(ZSWAP32(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
|
2
src/engine/external/zlib/crc32.h
vendored
|
@ -2,7 +2,7 @@
|
|||
* Generated automatically by crc32.c
|
||||
*/
|
||||
|
||||
local const unsigned long FAR crc_table[TBLS][256] =
|
||||
local const z_crc_t FAR crc_table[TBLS][256] =
|
||||
{
|
||||
{
|
||||
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||
|
|
1091
src/engine/external/zlib/deflate.c
vendored
45
src/engine/external/zlib/deflate.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -48,13 +48,19 @@
|
|||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define EXTRA_STATE 69
|
||||
#define NAME_STATE 73
|
||||
#define COMMENT_STATE 91
|
||||
#define HCRC_STATE 103
|
||||
#define BUSY_STATE 113
|
||||
#define FINISH_STATE 666
|
||||
#define Buf_size 16
|
||||
/* size of bit buffer in bi_buf */
|
||||
|
||||
#define INIT_STATE 42 /* zlib header -> BUSY_STATE */
|
||||
#ifdef GZIP
|
||||
# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */
|
||||
#endif
|
||||
#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */
|
||||
#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */
|
||||
#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */
|
||||
#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */
|
||||
#define BUSY_STATE 113 /* deflate -> FINISH_STATE */
|
||||
#define FINISH_STATE 666 /* stream complete */
|
||||
/* Stream status */
|
||||
|
||||
|
||||
|
@ -80,7 +86,7 @@ typedef struct static_tree_desc_s static_tree_desc;
|
|||
typedef struct tree_desc_s {
|
||||
ct_data *dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
const static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
|
@ -97,11 +103,11 @@ typedef struct internal_state {
|
|||
Bytef *pending_buf; /* output still pending */
|
||||
ulg pending_buf_size; /* size of pending_buf */
|
||||
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||
uInt pending; /* nb of bytes in the pending buffer */
|
||||
ulg pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
gz_headerp gzhead; /* gzip header information to write */
|
||||
uInt gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
ulg gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* can only be DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
@ -188,7 +194,7 @@ typedef struct internal_state {
|
|||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||
/* Didn't use ct_data typedef below to suppress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
@ -244,9 +250,9 @@ typedef struct internal_state {
|
|||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
uInt insert; /* bytes at end of window left to insert */
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
|
||||
#endif
|
||||
|
@ -272,7 +278,7 @@ typedef struct internal_state {
|
|||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||
|
@ -294,6 +300,7 @@ void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
|
|||
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
|
||||
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
|
||||
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
|
@ -305,7 +312,7 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
|||
* used.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG
|
||||
#ifndef ZLIB_DEBUG
|
||||
/* Inline versions of _tr_tally for speed: */
|
||||
|
||||
#if defined(GEN_TREES_H) || !defined(STDC)
|
||||
|
@ -324,8 +331,8 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
|||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (length); \
|
||||
ush dist = (distance); \
|
||||
{ uch len = (uch)(length); \
|
||||
ush dist = (ush)(distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
dist--; \
|
||||
|
|
218
src/engine/external/zlib/gzguts.h
vendored
Normal file
|
@ -0,0 +1,218 @@
|
|||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
# ifndef _LARGEFILE_SOURCE
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
# endif
|
||||
# ifdef _FILE_OFFSET_BITS
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zlib.h"
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
# define _POSIX_SOURCE
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# define WIDECHAR
|
||||
#endif
|
||||
|
||||
#ifdef WINAPI_FAMILY
|
||||
# define open _open
|
||||
# define read _read
|
||||
# define write _write
|
||||
# define close _close
|
||||
#endif
|
||||
|
||||
#ifdef NO_DEFLATE /* for compatibility with old definition */
|
||||
# define NO_GZCOMPRESS
|
||||
#endif
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef MSDOS
|
||||
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||
but for now we just assume it doesn't. */
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __OS400__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __MVS__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* unlike snprintf (which is required in C99), _snprintf does not guarantee
|
||||
null termination of the result -- however this is only used in gzlib.c where
|
||||
the result is assured to fit in the space provided */
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* since "static" is used to mean two completely different things in C, we
|
||||
define "local" for the non-static meaning of "static", for readability
|
||||
(compile with -Dlocal if your debugger can't find static symbols) */
|
||||
|
||||
/* gz* functions always use library allocation functions */
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
/* get errno and strerror definition */
|
||||
#if defined UNDER_CE
|
||||
# include <windows.h>
|
||||
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
|
||||
#else
|
||||
# ifndef NO_STRERROR
|
||||
# include <errno.h>
|
||||
# define zstrerror() strerror(errno)
|
||||
# else
|
||||
# define zstrerror() "stdio error (consult errno)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
|
||||
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
|
||||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
#endif
|
||||
|
||||
/* default memLevel */
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
|
||||
/* default i/o buffer size -- double this for output when reading (this and
|
||||
twice this must be able to fit in an unsigned type) */
|
||||
#define GZBUFSIZE 8192
|
||||
|
||||
/* gzip modes, also provide a little integrity check on the passed structure */
|
||||
#define GZ_NONE 0
|
||||
#define GZ_READ 7247
|
||||
#define GZ_WRITE 31153
|
||||
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
|
||||
|
||||
/* values for gz_state how */
|
||||
#define LOOK 0 /* look for a gzip header */
|
||||
#define COPY 1 /* copy input directly */
|
||||
#define GZIP 2 /* decompress a gzip stream */
|
||||
|
||||
/* internal gzip file state data structure */
|
||||
typedef struct {
|
||||
/* exposed contents for gzgetc() macro */
|
||||
struct gzFile_s x; /* "x" for exposed */
|
||||
/* x.have: number of bytes available at x.next */
|
||||
/* x.next: next output data to deliver or write */
|
||||
/* x.pos: current position in uncompressed data */
|
||||
/* used for both reading and writing */
|
||||
int mode; /* see gzip modes above */
|
||||
int fd; /* file descriptor */
|
||||
char *path; /* path or fd for error messages */
|
||||
unsigned size; /* buffer size, zero if not allocated yet */
|
||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
||||
unsigned char *in; /* input buffer (double-sized when writing) */
|
||||
unsigned char *out; /* output buffer (double-sized when reading) */
|
||||
int direct; /* 0 if processing gzip, 1 if transparent */
|
||||
/* just for reading */
|
||||
int how; /* 0: get header, 1: copy, 2: decompress */
|
||||
z_off64_t start; /* where the gzip data started, for rewinding */
|
||||
int eof; /* true if end of input file reached */
|
||||
int past; /* true if read requested past end */
|
||||
/* just for writing */
|
||||
int level; /* compression level */
|
||||
int strategy; /* compression strategy */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
/* error information */
|
||||
int err; /* error code */
|
||||
char *msg; /* error message */
|
||||
/* zlib inflate or deflate stream */
|
||||
z_stream strm; /* stream structure in-place (not a pointer) */
|
||||
} gz_state;
|
||||
typedef gz_state FAR *gz_statep;
|
||||
|
||||
/* shared functions */
|
||||
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
|
||||
#if defined UNDER_CE
|
||||
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
|
||||
#endif
|
||||
|
||||
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
|
||||
value -- needed when comparing unsigned to z_off64_t, which is signed
|
||||
(possible z_off64_t types off_t, off64_t, and long are all signed) */
|
||||
#ifdef INT_MAX
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
|
||||
#else
|
||||
unsigned ZLIB_INTERNAL gz_intmax OF((void));
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
|
||||
#endif
|
18
src/engine/external/zlib/infback.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2009 Mark Adler
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -42,17 +42,26 @@ int stream_size;
|
|||
return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
#endif
|
||||
}
|
||||
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||
if (strm->zfree == (free_func)0)
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zfree = zcfree;
|
||||
#endif
|
||||
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||
sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = windowBits;
|
||||
state->wbits = (uInt)windowBits;
|
||||
state->wsize = 1U << windowBits;
|
||||
state->window = window;
|
||||
state->wnext = 0;
|
||||
|
@ -246,7 +255,7 @@ out_func out;
|
|||
void FAR *out_desc;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *next; /* next input */
|
||||
z_const unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
|
@ -394,7 +403,6 @@ void FAR *out_desc;
|
|||
PULLBYTE();
|
||||
}
|
||||
if (here.val < 16) {
|
||||
NEEDBITS(here.bits);
|
||||
DROPBITS(here.bits);
|
||||
state->lens[state->have++] = here.val;
|
||||
}
|
||||
|
|
89
src/engine/external/zlib/inffast.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2008, 2010 Mark Adler
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -8,26 +8,9 @@
|
|||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
#ifndef ASMINF
|
||||
|
||||
/* Allow machine dependent optimization for post-increment or pre-increment.
|
||||
Based on testing to date,
|
||||
Pre-increment preferred for:
|
||||
- PowerPC G3 (Adler)
|
||||
- MIPS R5000 (Randers-Pehrson)
|
||||
Post-increment preferred for:
|
||||
- none
|
||||
No measurable difference:
|
||||
- Pentium III (Anderson)
|
||||
- M68060 (Nikl)
|
||||
*/
|
||||
#ifdef POSTINC
|
||||
# define OFF 0
|
||||
# define PUP(a) *(a)++
|
||||
#ifdef ASMINF
|
||||
# pragma message("Assembler code may have bugs -- use at your own risk")
|
||||
#else
|
||||
# define OFF 1
|
||||
# define PUP(a) *++(a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
Decode literal, length, and distance codes and write out the resulting
|
||||
|
@ -69,8 +52,8 @@ z_streamp strm;
|
|||
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *in; /* local strm->next_in */
|
||||
unsigned char FAR *last; /* while in < last, enough input available */
|
||||
z_const unsigned char FAR *in; /* local strm->next_in */
|
||||
z_const unsigned char FAR *last; /* have enough input while in < last */
|
||||
unsigned char FAR *out; /* local strm->next_out */
|
||||
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
|
||||
unsigned char FAR *end; /* while out < end, enough space available */
|
||||
|
@ -96,9 +79,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
|
||||
/* copy state to local variables */
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
in = strm->next_in - OFF;
|
||||
in = strm->next_in;
|
||||
last = in + (strm->avail_in - 5);
|
||||
out = strm->next_out - OFF;
|
||||
out = strm->next_out;
|
||||
beg = out - (start - strm->avail_out);
|
||||
end = out + (strm->avail_out - 257);
|
||||
#ifdef INFLATE_STRICT
|
||||
|
@ -119,9 +102,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
input data or output space */
|
||||
do {
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = lcode[hold & lmask];
|
||||
|
@ -134,14 +117,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
PUP(out) = (unsigned char)(here.val);
|
||||
*out++ = (unsigned char)(here.val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
len += (unsigned)hold & ((1U << op) - 1);
|
||||
|
@ -150,9 +133,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", len));
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = dcode[hold & dmask];
|
||||
|
@ -165,10 +148,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
dist = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
}
|
||||
|
@ -196,30 +179,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
||||
if (len <= op - whave) {
|
||||
do {
|
||||
PUP(out) = 0;
|
||||
*out++ = 0;
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
len -= op - whave;
|
||||
do {
|
||||
PUP(out) = 0;
|
||||
*out++ = 0;
|
||||
} while (--op > whave);
|
||||
if (op == 0) {
|
||||
from = out - dist;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
from = window - OFF;
|
||||
from = window;
|
||||
if (wnext == 0) { /* very common case */
|
||||
from += wsize - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
|
@ -230,14 +213,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
if (op < len) { /* some from end of window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = window - OFF;
|
||||
from = window;
|
||||
if (wnext < len) { /* some from start of window */
|
||||
op = wnext;
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
|
@ -248,35 +231,35 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
while (len > 2) {
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
len -= 3;
|
||||
}
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
from = out - dist; /* copy direct from output */
|
||||
do { /* minimum length is three */
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
len -= 3;
|
||||
} while (len > 2);
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
*out++ = *from++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,8 +296,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
|
|||
hold &= (1U << bits) - 1;
|
||||
|
||||
/* update state and return */
|
||||
strm->next_in = in + OFF;
|
||||
strm->next_out = out + OFF;
|
||||
strm->next_in = in;
|
||||
strm->next_out = out;
|
||||
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
||||
strm->avail_out = (unsigned)(out < end ?
|
||||
257 + (end - out) : 257 - (out - end));
|
||||
|
|
6
src/engine/external/zlib/inffixed.h
vendored
|
@ -2,9 +2,9 @@
|
|||
* Generated automatically by makefixed().
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It
|
||||
is part of the implementation of the compression library and
|
||||
is subject to change. Applications should only use zlib.h.
|
||||
/* WARNING: this file should *not* be used by applications.
|
||||
It is part of the implementation of this library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
static const code lenfix[512] = {
|
||||
|
|
253
src/engine/external/zlib/inflate.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* inflate.c -- zlib decompression
|
||||
* Copyright (C) 1995-2010 Mark Adler
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -92,32 +92,46 @@
|
|||
#endif
|
||||
|
||||
/* function prototypes */
|
||||
local int inflateStateCheck OF((z_streamp strm));
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
local int updatewindow OF((z_streamp strm, unsigned out));
|
||||
local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
|
||||
unsigned copy));
|
||||
#ifdef BUILDFIXED
|
||||
void makefixed OF((void));
|
||||
#endif
|
||||
local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
|
||||
local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
|
||||
unsigned len));
|
||||
|
||||
int ZEXPORT inflateReset(strm)
|
||||
local int inflateStateCheck(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
if (strm == Z_NULL ||
|
||||
strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
|
||||
return 1;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (state == Z_NULL || state->strm != strm ||
|
||||
state->mode < HEAD || state->mode > SYNC)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateResetKeep(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
strm->total_in = strm->total_out = state->total = 0;
|
||||
strm->msg = Z_NULL;
|
||||
strm->adler = 1; /* to support ill-conceived Java test suite */
|
||||
if (state->wrap) /* to support ill-conceived Java test suite */
|
||||
strm->adler = state->wrap & 1;
|
||||
state->mode = HEAD;
|
||||
state->last = 0;
|
||||
state->havedict = 0;
|
||||
state->dmax = 32768U;
|
||||
state->head = Z_NULL;
|
||||
state->wsize = 0;
|
||||
state->whave = 0;
|
||||
state->wnext = 0;
|
||||
state->hold = 0;
|
||||
state->bits = 0;
|
||||
state->lencode = state->distcode = state->next = state->codes;
|
||||
|
@ -127,6 +141,19 @@ z_streamp strm;
|
|||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateReset(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
state->wsize = 0;
|
||||
state->whave = 0;
|
||||
state->wnext = 0;
|
||||
return inflateResetKeep(strm);
|
||||
}
|
||||
|
||||
int ZEXPORT inflateReset2(strm, windowBits)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
|
@ -135,7 +162,7 @@ int windowBits;
|
|||
struct inflate_state FAR *state;
|
||||
|
||||
/* get the state */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* extract wrap request from windowBits parameter */
|
||||
|
@ -144,7 +171,7 @@ int windowBits;
|
|||
windowBits = -windowBits;
|
||||
}
|
||||
else {
|
||||
wrap = (windowBits >> 4) + 1;
|
||||
wrap = (windowBits >> 4) + 5;
|
||||
#ifdef GUNZIP
|
||||
if (windowBits < 48)
|
||||
windowBits &= 15;
|
||||
|
@ -180,16 +207,27 @@ int stream_size;
|
|||
if (strm == Z_NULL) return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
#endif
|
||||
}
|
||||
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||
if (strm->zfree == (free_func)0)
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zfree = zcfree;
|
||||
#endif
|
||||
state = (struct inflate_state FAR *)
|
||||
ZALLOC(strm, 1, sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->strm = strm;
|
||||
state->window = Z_NULL;
|
||||
state->mode = HEAD; /* to pass state test in inflateReset2() */
|
||||
ret = inflateReset2(strm, windowBits);
|
||||
if (ret != Z_OK) {
|
||||
ZFREE(strm, state);
|
||||
|
@ -213,17 +251,17 @@ int value;
|
|||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (bits < 0) {
|
||||
state->hold = 0;
|
||||
state->bits = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
|
||||
if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
|
||||
value &= (1L << bits) - 1;
|
||||
state->hold += value << state->bits;
|
||||
state->bits += bits;
|
||||
state->hold += (unsigned)value << state->bits;
|
||||
state->bits += (uInt)bits;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
@ -321,8 +359,8 @@ void makefixed()
|
|||
low = 0;
|
||||
for (;;) {
|
||||
if ((low % 7) == 0) printf("\n ");
|
||||
printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
|
||||
state.lencode[low].val);
|
||||
printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
|
||||
state.lencode[low].bits, state.lencode[low].val);
|
||||
if (++low == size) break;
|
||||
putchar(',');
|
||||
}
|
||||
|
@ -355,12 +393,13 @@ void makefixed()
|
|||
output will fall in the output data, making match copies simpler and faster.
|
||||
The advantage may be dependent on the size of the processor's data caches.
|
||||
*/
|
||||
local int updatewindow(strm, out)
|
||||
local int updatewindow(strm, end, copy)
|
||||
z_streamp strm;
|
||||
unsigned out;
|
||||
const Bytef *end;
|
||||
unsigned copy;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned copy, dist;
|
||||
unsigned dist;
|
||||
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
|
@ -380,19 +419,18 @@ unsigned out;
|
|||
}
|
||||
|
||||
/* copy state->wsize or less output bytes into the circular window */
|
||||
copy = out - strm->avail_out;
|
||||
if (copy >= state->wsize) {
|
||||
zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
|
||||
zmemcpy(state->window, end - state->wsize, state->wsize);
|
||||
state->wnext = 0;
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
else {
|
||||
dist = state->wsize - state->wnext;
|
||||
if (dist > copy) dist = copy;
|
||||
zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
|
||||
zmemcpy(state->window + state->wnext, end - copy, dist);
|
||||
copy -= dist;
|
||||
if (copy) {
|
||||
zmemcpy(state->window, strm->next_out - copy, copy);
|
||||
zmemcpy(state->window, end - copy, copy);
|
||||
state->wnext = copy;
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
|
@ -499,11 +537,6 @@ unsigned out;
|
|||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Reverse the bytes in a 32-bit value */
|
||||
#define REVERSE(q) \
|
||||
((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
|
||||
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
|
||||
|
||||
/*
|
||||
inflate() uses a state machine to process as much input data and generate as
|
||||
much output data as possible before returning. The state machine is
|
||||
|
@ -591,7 +624,7 @@ z_streamp strm;
|
|||
int flush;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *next; /* next input */
|
||||
z_const unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
|
@ -609,7 +642,7 @@ int flush;
|
|||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
|
||||
if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
|
||||
(strm->next_in == Z_NULL && strm->avail_in != 0))
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
|
@ -629,6 +662,8 @@ int flush;
|
|||
NEEDBITS(16);
|
||||
#ifdef GUNZIP
|
||||
if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
|
||||
if (state->wbits == 0)
|
||||
state->wbits = 15;
|
||||
state->check = crc32(0L, Z_NULL, 0);
|
||||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
|
@ -656,7 +691,7 @@ int flush;
|
|||
len = BITS(4) + 8;
|
||||
if (state->wbits == 0)
|
||||
state->wbits = len;
|
||||
else if (len > state->wbits) {
|
||||
if (len > 15 || len > state->wbits) {
|
||||
strm->msg = (char *)"invalid window size";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
|
@ -683,14 +718,16 @@ int flush;
|
|||
}
|
||||
if (state->head != Z_NULL)
|
||||
state->head->text = (int)((hold >> 8) & 1);
|
||||
if (state->flags & 0x0200) CRC2(state->check, hold);
|
||||
if ((state->flags & 0x0200) && (state->wrap & 4))
|
||||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = TIME;
|
||||
case TIME:
|
||||
NEEDBITS(32);
|
||||
if (state->head != Z_NULL)
|
||||
state->head->time = hold;
|
||||
if (state->flags & 0x0200) CRC4(state->check, hold);
|
||||
if ((state->flags & 0x0200) && (state->wrap & 4))
|
||||
CRC4(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = OS;
|
||||
case OS:
|
||||
|
@ -699,7 +736,8 @@ int flush;
|
|||
state->head->xflags = (int)(hold & 0xff);
|
||||
state->head->os = (int)(hold >> 8);
|
||||
}
|
||||
if (state->flags & 0x0200) CRC2(state->check, hold);
|
||||
if ((state->flags & 0x0200) && (state->wrap & 4))
|
||||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
state->mode = EXLEN;
|
||||
case EXLEN:
|
||||
|
@ -708,7 +746,8 @@ int flush;
|
|||
state->length = (unsigned)(hold);
|
||||
if (state->head != Z_NULL)
|
||||
state->head->extra_len = (unsigned)hold;
|
||||
if (state->flags & 0x0200) CRC2(state->check, hold);
|
||||
if ((state->flags & 0x0200) && (state->wrap & 4))
|
||||
CRC2(state->check, hold);
|
||||
INITBITS();
|
||||
}
|
||||
else if (state->head != Z_NULL)
|
||||
|
@ -726,7 +765,7 @@ int flush;
|
|||
len + copy > state->head->extra_max ?
|
||||
state->head->extra_max - len : copy);
|
||||
}
|
||||
if (state->flags & 0x0200)
|
||||
if ((state->flags & 0x0200) && (state->wrap & 4))
|
||||
state->check = crc32(state->check, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
|
@ -745,9 +784,9 @@ int flush;
|
|||
if (state->head != Z_NULL &&
|
||||
state->head->name != Z_NULL &&
|
||||
state->length < state->head->name_max)
|
||||
state->head->name[state->length++] = len;
|
||||
state->head->name[state->length++] = (Bytef)len;
|
||||
} while (len && copy < have);
|
||||
if (state->flags & 0x0200)
|
||||
if ((state->flags & 0x0200) && (state->wrap & 4))
|
||||
state->check = crc32(state->check, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
|
@ -766,9 +805,9 @@ int flush;
|
|||
if (state->head != Z_NULL &&
|
||||
state->head->comment != Z_NULL &&
|
||||
state->length < state->head->comm_max)
|
||||
state->head->comment[state->length++] = len;
|
||||
state->head->comment[state->length++] = (Bytef)len;
|
||||
} while (len && copy < have);
|
||||
if (state->flags & 0x0200)
|
||||
if ((state->flags & 0x0200) && (state->wrap & 4))
|
||||
state->check = crc32(state->check, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
|
@ -780,7 +819,7 @@ int flush;
|
|||
case HCRC:
|
||||
if (state->flags & 0x0200) {
|
||||
NEEDBITS(16);
|
||||
if (hold != (state->check & 0xffff)) {
|
||||
if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
|
||||
strm->msg = (char *)"header crc mismatch";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
|
@ -797,7 +836,7 @@ int flush;
|
|||
#endif
|
||||
case DICTID:
|
||||
NEEDBITS(32);
|
||||
strm->adler = state->check = REVERSE(hold);
|
||||
strm->adler = state->check = ZSWAP32(hold);
|
||||
INITBITS();
|
||||
state->mode = DICT;
|
||||
case DICT:
|
||||
|
@ -905,7 +944,7 @@ int flush;
|
|||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lencode = (const code FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
|
@ -925,7 +964,6 @@ int flush;
|
|||
PULLBYTE();
|
||||
}
|
||||
if (here.val < 16) {
|
||||
NEEDBITS(here.bits);
|
||||
DROPBITS(here.bits);
|
||||
state->lens[state->have++] = here.val;
|
||||
}
|
||||
|
@ -980,7 +1018,7 @@ int flush;
|
|||
values here (9 and 6) without reading the comments in inftrees.h
|
||||
concerning the ENOUGH constants, which depend on those values */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lencode = (const code FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
|
@ -989,7 +1027,7 @@ int flush;
|
|||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distcode = (const code FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
|
@ -1162,15 +1200,15 @@ int flush;
|
|||
out -= left;
|
||||
strm->total_out += out;
|
||||
state->total += out;
|
||||
if (out)
|
||||
if ((state->wrap & 4) && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, put - out, out);
|
||||
out = left;
|
||||
if ((
|
||||
if ((state->wrap & 4) && (
|
||||
#ifdef GUNZIP
|
||||
state->flags ? hold :
|
||||
#endif
|
||||
REVERSE(hold)) != state->check) {
|
||||
ZSWAP32(hold)) != state->check) {
|
||||
strm->msg = (char *)"incorrect data check";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
|
@ -1214,8 +1252,9 @@ int flush;
|
|||
*/
|
||||
inf_leave:
|
||||
RESTORE();
|
||||
if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
|
||||
if (updatewindow(strm, out)) {
|
||||
if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
|
||||
(state->mode < CHECK || flush != Z_FINISH)))
|
||||
if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
|
||||
state->mode = MEM;
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
|
@ -1224,10 +1263,10 @@ int flush;
|
|||
strm->total_in += in;
|
||||
strm->total_out += out;
|
||||
state->total += out;
|
||||
if (state->wrap && out)
|
||||
if ((state->wrap & 4) && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, strm->next_out - out, out);
|
||||
strm->data_type = state->bits + (state->last ? 64 : 0) +
|
||||
strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
|
||||
(state->mode == TYPE ? 128 : 0) +
|
||||
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
|
||||
if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
|
||||
|
@ -1239,7 +1278,7 @@ int ZEXPORT inflateEnd(strm)
|
|||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
if (inflateStateCheck(strm))
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (state->window != Z_NULL) ZFREE(strm, state->window);
|
||||
|
@ -1249,43 +1288,59 @@ z_streamp strm;
|
|||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
|
||||
z_streamp strm;
|
||||
Bytef *dictionary;
|
||||
uInt *dictLength;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
/* check state */
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* copy dictionary */
|
||||
if (state->whave && dictionary != Z_NULL) {
|
||||
zmemcpy(dictionary, state->window + state->wnext,
|
||||
state->whave - state->wnext);
|
||||
zmemcpy(dictionary + state->whave - state->wnext,
|
||||
state->window, state->wnext);
|
||||
}
|
||||
if (dictLength != Z_NULL)
|
||||
*dictLength = state->whave;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
|
||||
z_streamp strm;
|
||||
const Bytef *dictionary;
|
||||
uInt dictLength;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned long id;
|
||||
unsigned long dictid;
|
||||
int ret;
|
||||
|
||||
/* check state */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (state->wrap != 0 && state->mode != DICT)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for correct dictionary id */
|
||||
/* check for correct dictionary identifier */
|
||||
if (state->mode == DICT) {
|
||||
id = adler32(0L, Z_NULL, 0);
|
||||
id = adler32(id, dictionary, dictLength);
|
||||
if (id != state->check)
|
||||
dictid = adler32(0L, Z_NULL, 0);
|
||||
dictid = adler32(dictid, dictionary, dictLength);
|
||||
if (dictid != state->check)
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* copy dictionary to window */
|
||||
if (updatewindow(strm, strm->avail_out)) {
|
||||
/* copy dictionary to window using updatewindow(), which will amend the
|
||||
existing dictionary if appropriate */
|
||||
ret = updatewindow(strm, dictionary + dictLength, dictLength);
|
||||
if (ret) {
|
||||
state->mode = MEM;
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
if (dictLength > state->wsize) {
|
||||
zmemcpy(state->window, dictionary + dictLength - state->wsize,
|
||||
state->wsize);
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
else {
|
||||
zmemcpy(state->window + state->wsize - dictLength, dictionary,
|
||||
dictLength);
|
||||
state->whave = dictLength;
|
||||
}
|
||||
state->havedict = 1;
|
||||
Tracev((stderr, "inflate: dictionary set\n"));
|
||||
return Z_OK;
|
||||
|
@ -1298,7 +1353,7 @@ gz_headerp head;
|
|||
struct inflate_state FAR *state;
|
||||
|
||||
/* check state */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
|
||||
|
||||
|
@ -1321,7 +1376,7 @@ gz_headerp head;
|
|||
*/
|
||||
local unsigned syncsearch(have, buf, len)
|
||||
unsigned FAR *have;
|
||||
unsigned char FAR *buf;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned got;
|
||||
|
@ -1351,7 +1406,7 @@ z_streamp strm;
|
|||
struct inflate_state FAR *state;
|
||||
|
||||
/* check parameters */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
|
||||
|
||||
|
@ -1398,7 +1453,7 @@ z_streamp strm;
|
|||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
return state->mode == STORED && state->bits == 0;
|
||||
}
|
||||
|
@ -1413,8 +1468,7 @@ z_streamp source;
|
|||
unsigned wsize;
|
||||
|
||||
/* check input */
|
||||
if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
|
||||
source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
|
||||
if (inflateStateCheck(source) || dest == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)source->state;
|
||||
|
||||
|
@ -1433,8 +1487,9 @@ z_streamp source;
|
|||
}
|
||||
|
||||
/* copy state */
|
||||
zmemcpy(dest, source, sizeof(z_stream));
|
||||
zmemcpy(copy, state, sizeof(struct inflate_state));
|
||||
zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
|
||||
zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
|
||||
copy->strm = dest;
|
||||
if (state->lencode >= state->codes &&
|
||||
state->lencode <= state->codes + ENOUGH - 1) {
|
||||
copy->lencode = copy->codes + (state->lencode - state->codes);
|
||||
|
@ -1456,25 +1511,51 @@ int subvert;
|
|||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
state->sane = !subvert;
|
||||
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
||||
state->sane = !subvert;
|
||||
return Z_OK;
|
||||
#else
|
||||
(void)subvert;
|
||||
state->sane = 1;
|
||||
return Z_DATA_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZEXPORT inflateValidate(strm, check)
|
||||
z_streamp strm;
|
||||
int check;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
if (check)
|
||||
state->wrap |= 4;
|
||||
else
|
||||
state->wrap &= ~4;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
long ZEXPORT inflateMark(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
|
||||
if (inflateStateCheck(strm))
|
||||
return -(1L << 16);
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
return ((long)(state->back) << 16) +
|
||||
return (long)(((unsigned long)((long)state->back)) << 16) +
|
||||
(state->mode == COPY ? state->length :
|
||||
(state->mode == MATCH ? state->was - state->length : 0));
|
||||
}
|
||||
|
||||
unsigned long ZEXPORT inflateCodesUsed(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
if (inflateStateCheck(strm)) return (unsigned long)-1;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
return (unsigned long)(state->next - state->codes);
|
||||
}
|
||||
|
|
11
src/engine/external/zlib/inflate.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* inflate.h -- internal inflate state definition
|
||||
* Copyright (C) 1995-2009 Mark Adler
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
/* Possible inflate modes between inflate() calls */
|
||||
typedef enum {
|
||||
HEAD, /* i: waiting for magic header */
|
||||
HEAD = 16180, /* i: waiting for magic header */
|
||||
FLAGS, /* i: waiting for method and flags (gzip) */
|
||||
TIME, /* i: waiting for modification time (gzip) */
|
||||
OS, /* i: waiting for extra flags and operating system (gzip) */
|
||||
|
@ -77,11 +77,14 @@ typedef enum {
|
|||
CHECK -> LENGTH -> DONE
|
||||
*/
|
||||
|
||||
/* state maintained between inflate() calls. Approximately 10K bytes. */
|
||||
/* State maintained between inflate() calls -- approximately 7K bytes, not
|
||||
including the allocated sliding window, which is up to 32K bytes. */
|
||||
struct inflate_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
inflate_mode mode; /* current inflate mode */
|
||||
int last; /* true if processing last block */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
|
||||
bit 2 true to validate check value */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
|
|
74
src/engine/external/zlib/inftrees.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2010 Mark Adler
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
|||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
|
||||
" inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
|
@ -54,7 +54,7 @@ unsigned short FAR *work;
|
|||
code FAR *next; /* next available space in table */
|
||||
const unsigned short FAR *base; /* base value table to use */
|
||||
const unsigned short FAR *extra; /* extra bits table to use */
|
||||
int end; /* use base and extra for symbol > end */
|
||||
unsigned match; /* use base and extra for symbol >= match */
|
||||
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||
|
@ -62,7 +62,7 @@ unsigned short FAR *work;
|
|||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
|
@ -181,19 +181,17 @@ unsigned short FAR *work;
|
|||
switch (type) {
|
||||
case CODES:
|
||||
base = extra = work; /* dummy value--not used */
|
||||
end = 19;
|
||||
match = 20;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
base -= 257;
|
||||
extra = lext;
|
||||
extra -= 257;
|
||||
end = 256;
|
||||
match = 257;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
end = -1;
|
||||
match = 0;
|
||||
}
|
||||
|
||||
/* initialize state for loop */
|
||||
|
@ -208,21 +206,21 @@ unsigned short FAR *work;
|
|||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
if ((type == LENS && used > ENOUGH_LENS) ||
|
||||
(type == DISTS && used > ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
for (;;) {
|
||||
/* create table entry */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
if ((int)(work[sym]) < end) {
|
||||
if (work[sym] + 1U < match) {
|
||||
here.op = (unsigned char)0;
|
||||
here.val = work[sym];
|
||||
}
|
||||
else if ((int)(work[sym]) > end) {
|
||||
here.op = (unsigned char)(extra[work[sym]]);
|
||||
here.val = base[work[sym]];
|
||||
else if (work[sym] >= match) {
|
||||
here.op = (unsigned char)(extra[work[sym] - match]);
|
||||
here.val = base[work[sym] - match];
|
||||
}
|
||||
else {
|
||||
here.op = (unsigned char)(32 + 64); /* end of block */
|
||||
|
@ -277,8 +275,8 @@ unsigned short FAR *work;
|
|||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
if ((type == LENS && used > ENOUGH_LENS) ||
|
||||
(type == DISTS && used > ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
|
@ -289,38 +287,14 @@ unsigned short FAR *work;
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||
loop above in incrementing huff for table indices. It is assumed that
|
||||
len is equal to curr + drop, so there is no loop needed to increment
|
||||
through high index bits. When the current sub-table is filled, the loop
|
||||
drops back to the root table to fill in any remaining entries there.
|
||||
*/
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
while (huff != 0) {
|
||||
/* when done with sub-table, drop back to root table */
|
||||
if (drop != 0 && (huff & mask) != low) {
|
||||
drop = 0;
|
||||
len = root;
|
||||
next = *table;
|
||||
here.bits = (unsigned char)len;
|
||||
}
|
||||
|
||||
/* put invalid code marker in table */
|
||||
next[huff >> drop] = here;
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
/* fill in remaining table entry if code is incomplete (guaranteed to have
|
||||
at most one remaining entry, since if the code is incomplete, the
|
||||
maximum code length that was allowed to get this far is one bit) */
|
||||
if (huff != 0) {
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
next[huff] = here;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
|
|
151
src/engine/external/zlib/trees.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* trees.c -- output deflated data using Huffman coding
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly
|
||||
* detect_data_type() function provided freely by Cosmin Truta, 2006
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
@ -36,7 +36,7 @@
|
|||
|
||||
#include "deflate.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
|
@ -74,11 +74,6 @@ local const uch bl_order[BL_CODES]
|
|||
* probability, to avoid transmitting the lengths for unused bit length codes.
|
||||
*/
|
||||
|
||||
#define Buf_size (8 * 2*sizeof(char))
|
||||
/* Number of bits used within bi_buf. (bi_buf might be implemented on
|
||||
* more than 16 bits on some systems.)
|
||||
*/
|
||||
|
||||
/* ===========================================================================
|
||||
* Local data. These are initialized only once.
|
||||
*/
|
||||
|
@ -127,13 +122,13 @@ struct static_tree_desc_s {
|
|||
int max_length; /* max bit length for the codes */
|
||||
};
|
||||
|
||||
local static_tree_desc static_l_desc =
|
||||
local const static_tree_desc static_l_desc =
|
||||
{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
|
||||
|
||||
local static_tree_desc static_d_desc =
|
||||
local const static_tree_desc static_d_desc =
|
||||
{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
|
||||
|
||||
local static_tree_desc static_bl_desc =
|
||||
local const static_tree_desc static_bl_desc =
|
||||
{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -151,24 +146,22 @@ local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
|
|||
local int build_bl_tree OF((deflate_state *s));
|
||||
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
|
||||
int blcodes));
|
||||
local void compress_block OF((deflate_state *s, ct_data *ltree,
|
||||
ct_data *dtree));
|
||||
local void compress_block OF((deflate_state *s, const ct_data *ltree,
|
||||
const ct_data *dtree));
|
||||
local int detect_data_type OF((deflate_state *s));
|
||||
local unsigned bi_reverse OF((unsigned value, int length));
|
||||
local void bi_windup OF((deflate_state *s));
|
||||
local void bi_flush OF((deflate_state *s));
|
||||
local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
|
||||
int header));
|
||||
|
||||
#ifdef GEN_TREES_H
|
||||
local void gen_trees_header OF((void));
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG
|
||||
#ifndef ZLIB_DEBUG
|
||||
# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
|
||||
/* Send a code of the given tree. c and tree must not have side effects */
|
||||
|
||||
#else /* DEBUG */
|
||||
#else /* !ZLIB_DEBUG */
|
||||
# define send_code(s, c, tree) \
|
||||
{ if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
|
||||
send_bits(s, tree[c].Code, tree[c].Len); }
|
||||
|
@ -187,7 +180,7 @@ local void gen_trees_header OF((void));
|
|||
* Send a value on a given number of bits.
|
||||
* IN assertion: length <= 16 and value fits in length bits.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
local void send_bits OF((deflate_state *s, int value, int length));
|
||||
|
||||
local void send_bits(s, value, length)
|
||||
|
@ -213,12 +206,12 @@ local void send_bits(s, value, length)
|
|||
s->bi_valid += length;
|
||||
}
|
||||
}
|
||||
#else /* !DEBUG */
|
||||
#else /* !ZLIB_DEBUG */
|
||||
|
||||
#define send_bits(s, value, length) \
|
||||
{ int len = length;\
|
||||
if (s->bi_valid > (int)Buf_size - len) {\
|
||||
int val = value;\
|
||||
int val = (int)value;\
|
||||
s->bi_buf |= (ush)val << s->bi_valid;\
|
||||
put_short(s, s->bi_buf);\
|
||||
s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
|
||||
|
@ -228,7 +221,7 @@ local void send_bits(s, value, length)
|
|||
s->bi_valid += len;\
|
||||
}\
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
#endif /* ZLIB_DEBUG */
|
||||
|
||||
|
||||
/* the arguments must not have side effects */
|
||||
|
@ -322,7 +315,7 @@ local void tr_static_init()
|
|||
* Genererate the file trees.h describing the static trees.
|
||||
*/
|
||||
#ifdef GEN_TREES_H
|
||||
# ifndef DEBUG
|
||||
# ifndef ZLIB_DEBUG
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
|
||||
|
@ -399,8 +392,7 @@ void ZLIB_INTERNAL _tr_init(s)
|
|||
|
||||
s->bi_buf = 0;
|
||||
s->bi_valid = 0;
|
||||
s->last_eob_len = 8; /* enough lookahead for inflate */
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len = 0L;
|
||||
s->bits_sent = 0L;
|
||||
#endif
|
||||
|
@ -528,12 +520,12 @@ local void gen_bitlen(s, desc)
|
|||
xbits = 0;
|
||||
if (n >= base) xbits = extra[n-base];
|
||||
f = tree[n].Freq;
|
||||
s->opt_len += (ulg)f * (bits + xbits);
|
||||
if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
|
||||
s->opt_len += (ulg)f * (unsigned)(bits + xbits);
|
||||
if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
|
||||
}
|
||||
if (overflow == 0) return;
|
||||
|
||||
Trace((stderr,"\nbit length overflow\n"));
|
||||
Tracev((stderr,"\nbit length overflow\n"));
|
||||
/* This happens for example on obj2 and pic of the Calgary corpus */
|
||||
|
||||
/* Find the first bit length which could increase: */
|
||||
|
@ -560,9 +552,8 @@ local void gen_bitlen(s, desc)
|
|||
m = s->heap[--h];
|
||||
if (m > max_code) continue;
|
||||
if ((unsigned) tree[m].Len != (unsigned) bits) {
|
||||
Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
|
||||
s->opt_len += ((long)bits - (long)tree[m].Len)
|
||||
*(long)tree[m].Freq;
|
||||
Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
|
||||
s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;
|
||||
tree[m].Len = (ush)bits;
|
||||
}
|
||||
n--;
|
||||
|
@ -584,7 +575,7 @@ local void gen_codes (tree, max_code, bl_count)
|
|||
ushf *bl_count; /* number of codes at each bit length */
|
||||
{
|
||||
ush next_code[MAX_BITS+1]; /* next code value for each bit length */
|
||||
ush code = 0; /* running code value */
|
||||
unsigned code = 0; /* running code value */
|
||||
int bits; /* bit index */
|
||||
int n; /* code index */
|
||||
|
||||
|
@ -592,7 +583,8 @@ local void gen_codes (tree, max_code, bl_count)
|
|||
* without bit reversal.
|
||||
*/
|
||||
for (bits = 1; bits <= MAX_BITS; bits++) {
|
||||
next_code[bits] = code = (code + bl_count[bits-1]) << 1;
|
||||
code = (code + bl_count[bits-1]) << 1;
|
||||
next_code[bits] = (ush)code;
|
||||
}
|
||||
/* Check that the bit counts in bl_count are consistent. The last code
|
||||
* must be all ones.
|
||||
|
@ -605,7 +597,7 @@ local void gen_codes (tree, max_code, bl_count)
|
|||
int len = tree[n].Len;
|
||||
if (len == 0) continue;
|
||||
/* Now reverse the bits */
|
||||
tree[n].Code = bi_reverse(next_code[len]++, len);
|
||||
tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
|
||||
|
||||
Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
|
||||
n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
|
||||
|
@ -827,7 +819,7 @@ local int build_bl_tree(s)
|
|||
if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
|
||||
}
|
||||
/* Update opt_len to include the bit length tree and counts */
|
||||
s->opt_len += 3*(max_blindex+1) + 5+5+4;
|
||||
s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4;
|
||||
Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
|
||||
s->opt_len, s->static_len));
|
||||
|
||||
|
@ -875,52 +867,46 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
|
|||
int last; /* one if this is the last block for a file */
|
||||
{
|
||||
send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */
|
||||
#ifdef DEBUG
|
||||
bi_windup(s); /* align on byte boundary */
|
||||
put_short(s, (ush)stored_len);
|
||||
put_short(s, (ush)~stored_len);
|
||||
zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
|
||||
s->pending += stored_len;
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
|
||||
s->compressed_len += (stored_len + 4) << 3;
|
||||
s->bits_sent += 2*16;
|
||||
s->bits_sent += stored_len<<3;
|
||||
#endif
|
||||
copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
|
||||
*/
|
||||
void ZLIB_INTERNAL _tr_flush_bits(s)
|
||||
deflate_state *s;
|
||||
{
|
||||
bi_flush(s);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Send one empty static block to give enough lookahead for inflate.
|
||||
* This takes 10 bits, of which 7 may remain in the bit buffer.
|
||||
* The current inflate code requires 9 bits of lookahead. If the
|
||||
* last two codes for the previous block (real code plus EOB) were coded
|
||||
* on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
|
||||
* the last real code. In this case we send two empty static blocks instead
|
||||
* of one. (There are no problems if the previous block is stored or fixed.)
|
||||
* To simplify the code, we assume the worst case of last real code encoded
|
||||
* on one bit only.
|
||||
*/
|
||||
void ZLIB_INTERNAL _tr_align(s)
|
||||
deflate_state *s;
|
||||
{
|
||||
send_bits(s, STATIC_TREES<<1, 3);
|
||||
send_code(s, END_BLOCK, static_ltree);
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
|
||||
#endif
|
||||
bi_flush(s);
|
||||
/* Of the 10 bits for the empty block, we have already sent
|
||||
* (10 - bi_valid) bits. The lookahead for the last real code (before
|
||||
* the EOB of the previous block) was thus at least one plus the length
|
||||
* of the EOB plus what we have just sent of the empty static block.
|
||||
*/
|
||||
if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
|
||||
send_bits(s, STATIC_TREES<<1, 3);
|
||||
send_code(s, END_BLOCK, static_ltree);
|
||||
#ifdef DEBUG
|
||||
s->compressed_len += 10L;
|
||||
#endif
|
||||
bi_flush(s);
|
||||
}
|
||||
s->last_eob_len = 7;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Determine the best encoding for the current block: dynamic trees, static
|
||||
* trees or store, and output the encoded block to the zip file.
|
||||
* trees or store, and write out the encoded block.
|
||||
*/
|
||||
void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
||||
deflate_state *s;
|
||||
|
@ -990,16 +976,18 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
|||
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
|
||||
#endif
|
||||
send_bits(s, (STATIC_TREES<<1)+last, 3);
|
||||
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
|
||||
#ifdef DEBUG
|
||||
compress_block(s, (const ct_data *)static_ltree,
|
||||
(const ct_data *)static_dtree);
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len += 3 + s->static_len;
|
||||
#endif
|
||||
} else {
|
||||
send_bits(s, (DYN_TREES<<1)+last, 3);
|
||||
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
|
||||
max_blindex+1);
|
||||
compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
|
||||
#ifdef DEBUG
|
||||
compress_block(s, (const ct_data *)s->dyn_ltree,
|
||||
(const ct_data *)s->dyn_dtree);
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len += 3 + s->opt_len;
|
||||
#endif
|
||||
}
|
||||
|
@ -1011,7 +999,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
|||
|
||||
if (last) {
|
||||
bi_windup(s);
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->compressed_len += 7; /* align on byte boundary */
|
||||
#endif
|
||||
}
|
||||
|
@ -1075,8 +1063,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
|||
*/
|
||||
local void compress_block(s, ltree, dtree)
|
||||
deflate_state *s;
|
||||
ct_data *ltree; /* literal tree */
|
||||
ct_data *dtree; /* distance tree */
|
||||
const ct_data *ltree; /* literal tree */
|
||||
const ct_data *dtree; /* distance tree */
|
||||
{
|
||||
unsigned dist; /* distance of matched string */
|
||||
int lc; /* match length or unmatched char (if dist == 0) */
|
||||
|
@ -1106,7 +1094,7 @@ local void compress_block(s, ltree, dtree)
|
|||
send_code(s, code, dtree); /* send the distance code */
|
||||
extra = extra_dbits[code];
|
||||
if (extra != 0) {
|
||||
dist -= base_dist[code];
|
||||
dist -= (unsigned)base_dist[code];
|
||||
send_bits(s, dist, extra); /* send the extra distance bits */
|
||||
}
|
||||
} /* literal or match pair ? */
|
||||
|
@ -1118,7 +1106,6 @@ local void compress_block(s, ltree, dtree)
|
|||
} while (lx < s->last_lit);
|
||||
|
||||
send_code(s, END_BLOCK, ltree);
|
||||
s->last_eob_len = ltree[END_BLOCK].Len;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -1210,35 +1197,7 @@ local void bi_windup(s)
|
|||
}
|
||||
s->bi_buf = 0;
|
||||
s->bi_valid = 0;
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
s->bits_sent = (s->bits_sent+7) & ~7;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Copy a stored block, storing first the length and its
|
||||
* one's complement if requested.
|
||||
*/
|
||||
local void copy_block(s, buf, len, header)
|
||||
deflate_state *s;
|
||||
charf *buf; /* the input data */
|
||||
unsigned len; /* its length */
|
||||
int header; /* true if block header must be written */
|
||||
{
|
||||
bi_windup(s); /* align on byte boundary */
|
||||
s->last_eob_len = 8; /* enough lookahead for inflate */
|
||||
|
||||
if (header) {
|
||||
put_short(s, (ush)len);
|
||||
put_short(s, (ush)~len);
|
||||
#ifdef DEBUG
|
||||
s->bits_sent += 2*16;
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
s->bits_sent += (ulg)len<<3;
|
||||
#endif
|
||||
while (len--) {
|
||||
put_byte(s, *buf++);
|
||||
}
|
||||
}
|
||||
|
|
114
src/engine/external/zlib/uncompr.c
vendored
|
@ -1,5 +1,5 @@
|
|||
/* uncompr.c -- decompress a memory buffer
|
||||
* Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -9,51 +9,85 @@
|
|||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be large enough to hold the
|
||||
entire uncompressed data. (The size of the uncompressed data must have
|
||||
been saved previously by the compressor and transmitted to the decompressor
|
||||
by some mechanism outside the scope of this compression library.)
|
||||
Upon exit, destLen is the actual size of the compressed buffer.
|
||||
Decompresses the source buffer into the destination buffer. *sourceLen is
|
||||
the byte length of the source buffer. Upon entry, *destLen is the total size
|
||||
of the destination buffer, which must be large enough to hold the entire
|
||||
uncompressed data. (The size of the uncompressed data must have been saved
|
||||
previously by the compressor and transmitted to the decompressor by some
|
||||
mechanism outside the scope of this compression library.) Upon exit,
|
||||
*destLen is the size of the decompressed data and *sourceLen is the number
|
||||
of source bytes consumed. Upon return, source + *sourceLen points to the
|
||||
first unused input byte.
|
||||
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
|
||||
Z_DATA_ERROR if the input data was corrupted, including if the input data is
|
||||
an incomplete zlib stream.
|
||||
*/
|
||||
int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong *sourceLen;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
const uInt max = (uInt)-1;
|
||||
uLong len, left;
|
||||
Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
|
||||
|
||||
len = *sourceLen;
|
||||
if (*destLen) {
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
}
|
||||
else {
|
||||
left = 1;
|
||||
dest = buf;
|
||||
}
|
||||
|
||||
stream.next_in = (z_const Bytef *)source;
|
||||
stream.avail_in = 0;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = 0;
|
||||
|
||||
do {
|
||||
if (stream.avail_out == 0) {
|
||||
stream.avail_out = left > (uLong)max ? max : (uInt)left;
|
||||
left -= stream.avail_out;
|
||||
}
|
||||
if (stream.avail_in == 0) {
|
||||
stream.avail_in = len > (uLong)max ? max : (uInt)len;
|
||||
len -= stream.avail_in;
|
||||
}
|
||||
err = inflate(&stream, Z_NO_FLUSH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*sourceLen -= len + stream.avail_in;
|
||||
if (dest != buf)
|
||||
*destLen = stream.total_out;
|
||||
else if (stream.total_out && err == Z_BUF_ERROR)
|
||||
left = 1;
|
||||
|
||||
inflateEnd(&stream);
|
||||
return err == Z_STREAM_END ? Z_OK :
|
||||
err == Z_NEED_DICT ? Z_DATA_ERROR :
|
||||
err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
|
||||
err;
|
||||
}
|
||||
|
||||
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
return Z_DATA_ERROR;
|
||||
return err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
return err;
|
||||
return uncompress2(dest, destLen, source, &sourceLen);
|
||||
}
|
||||
|
|
234
src/engine/external/zlib/zconf.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -15,11 +15,13 @@
|
|||
* this permanently in zconf.h using "./configure --zprefix".
|
||||
*/
|
||||
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
|
||||
# define Z_PREFIX_SET
|
||||
|
||||
/* all linked symbols */
|
||||
/* all linked symbols and init macros */
|
||||
# define _dist_code z__dist_code
|
||||
# define _length_code z__length_code
|
||||
# define _tr_align z__tr_align
|
||||
# define _tr_flush_bits z__tr_flush_bits
|
||||
# define _tr_flush_block z__tr_flush_block
|
||||
# define _tr_init z__tr_init
|
||||
# define _tr_stored_block z__tr_stored_block
|
||||
|
@ -27,81 +29,111 @@
|
|||
# define adler32 z_adler32
|
||||
# define adler32_combine z_adler32_combine
|
||||
# define adler32_combine64 z_adler32_combine64
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# define adler32_z z_adler32_z
|
||||
# ifndef Z_SOLO
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# endif
|
||||
# define crc32 z_crc32
|
||||
# define crc32_combine z_crc32_combine
|
||||
# define crc32_combine64 z_crc32_combine64
|
||||
# define crc32_z z_crc32_z
|
||||
# define deflate z_deflate
|
||||
# define deflateBound z_deflateBound
|
||||
# define deflateCopy z_deflateCopy
|
||||
# define deflateEnd z_deflateEnd
|
||||
# define deflateGetDictionary z_deflateGetDictionary
|
||||
# define deflateInit z_deflateInit
|
||||
# define deflateInit2 z_deflateInit2
|
||||
# define deflateInit2_ z_deflateInit2_
|
||||
# define deflateInit_ z_deflateInit_
|
||||
# define deflateParams z_deflateParams
|
||||
# define deflatePending z_deflatePending
|
||||
# define deflatePrime z_deflatePrime
|
||||
# define deflateReset z_deflateReset
|
||||
# define deflateResetKeep z_deflateResetKeep
|
||||
# define deflateSetDictionary z_deflateSetDictionary
|
||||
# define deflateSetHeader z_deflateSetHeader
|
||||
# define deflateTune z_deflateTune
|
||||
# define deflate_copyright z_deflate_copyright
|
||||
# define get_crc_table z_get_crc_table
|
||||
# define gz_error z_gz_error
|
||||
# define gz_intmax z_gz_intmax
|
||||
# define gz_strwinerror z_gz_strwinerror
|
||||
# define gzbuffer z_gzbuffer
|
||||
# define gzclearerr z_gzclearerr
|
||||
# define gzclose z_gzclose
|
||||
# define gzclose_r z_gzclose_r
|
||||
# define gzclose_w z_gzclose_w
|
||||
# define gzdirect z_gzdirect
|
||||
# define gzdopen z_gzdopen
|
||||
# define gzeof z_gzeof
|
||||
# define gzerror z_gzerror
|
||||
# define gzflush z_gzflush
|
||||
# define gzgetc z_gzgetc
|
||||
# define gzgets z_gzgets
|
||||
# define gzoffset z_gzoffset
|
||||
# define gzoffset64 z_gzoffset64
|
||||
# define gzopen z_gzopen
|
||||
# define gzopen64 z_gzopen64
|
||||
# define gzprintf z_gzprintf
|
||||
# define gzputc z_gzputc
|
||||
# define gzputs z_gzputs
|
||||
# define gzread z_gzread
|
||||
# define gzrewind z_gzrewind
|
||||
# define gzseek z_gzseek
|
||||
# define gzseek64 z_gzseek64
|
||||
# define gzsetparams z_gzsetparams
|
||||
# define gztell z_gztell
|
||||
# define gztell64 z_gztell64
|
||||
# define gzungetc z_gzungetc
|
||||
# define gzwrite z_gzwrite
|
||||
# ifndef Z_SOLO
|
||||
# define gz_error z_gz_error
|
||||
# define gz_intmax z_gz_intmax
|
||||
# define gz_strwinerror z_gz_strwinerror
|
||||
# define gzbuffer z_gzbuffer
|
||||
# define gzclearerr z_gzclearerr
|
||||
# define gzclose z_gzclose
|
||||
# define gzclose_r z_gzclose_r
|
||||
# define gzclose_w z_gzclose_w
|
||||
# define gzdirect z_gzdirect
|
||||
# define gzdopen z_gzdopen
|
||||
# define gzeof z_gzeof
|
||||
# define gzerror z_gzerror
|
||||
# define gzflush z_gzflush
|
||||
# define gzfread z_gzfread
|
||||
# define gzfwrite z_gzfwrite
|
||||
# define gzgetc z_gzgetc
|
||||
# define gzgetc_ z_gzgetc_
|
||||
# define gzgets z_gzgets
|
||||
# define gzoffset z_gzoffset
|
||||
# define gzoffset64 z_gzoffset64
|
||||
# define gzopen z_gzopen
|
||||
# define gzopen64 z_gzopen64
|
||||
# ifdef _WIN32
|
||||
# define gzopen_w z_gzopen_w
|
||||
# endif
|
||||
# define gzprintf z_gzprintf
|
||||
# define gzputc z_gzputc
|
||||
# define gzputs z_gzputs
|
||||
# define gzread z_gzread
|
||||
# define gzrewind z_gzrewind
|
||||
# define gzseek z_gzseek
|
||||
# define gzseek64 z_gzseek64
|
||||
# define gzsetparams z_gzsetparams
|
||||
# define gztell z_gztell
|
||||
# define gztell64 z_gztell64
|
||||
# define gzungetc z_gzungetc
|
||||
# define gzvprintf z_gzvprintf
|
||||
# define gzwrite z_gzwrite
|
||||
# endif
|
||||
# define inflate z_inflate
|
||||
# define inflateBack z_inflateBack
|
||||
# define inflateBackEnd z_inflateBackEnd
|
||||
# define inflateBackInit z_inflateBackInit
|
||||
# define inflateBackInit_ z_inflateBackInit_
|
||||
# define inflateCodesUsed z_inflateCodesUsed
|
||||
# define inflateCopy z_inflateCopy
|
||||
# define inflateEnd z_inflateEnd
|
||||
# define inflateGetDictionary z_inflateGetDictionary
|
||||
# define inflateGetHeader z_inflateGetHeader
|
||||
# define inflateInit z_inflateInit
|
||||
# define inflateInit2 z_inflateInit2
|
||||
# define inflateInit2_ z_inflateInit2_
|
||||
# define inflateInit_ z_inflateInit_
|
||||
# define inflateMark z_inflateMark
|
||||
# define inflatePrime z_inflatePrime
|
||||
# define inflateReset z_inflateReset
|
||||
# define inflateReset2 z_inflateReset2
|
||||
# define inflateResetKeep z_inflateResetKeep
|
||||
# define inflateSetDictionary z_inflateSetDictionary
|
||||
# define inflateSync z_inflateSync
|
||||
# define inflateSyncPoint z_inflateSyncPoint
|
||||
# define inflateUndermine z_inflateUndermine
|
||||
# define inflateValidate z_inflateValidate
|
||||
# define inflate_copyright z_inflate_copyright
|
||||
# define inflate_fast z_inflate_fast
|
||||
# define inflate_table z_inflate_table
|
||||
# define uncompress z_uncompress
|
||||
# ifndef Z_SOLO
|
||||
# define uncompress z_uncompress
|
||||
# define uncompress2 z_uncompress2
|
||||
# endif
|
||||
# define zError z_zError
|
||||
# define zcalloc z_zcalloc
|
||||
# define zcfree z_zcfree
|
||||
# ifndef Z_SOLO
|
||||
# define zcalloc z_zcalloc
|
||||
# define zcfree z_zcfree
|
||||
# endif
|
||||
# define zlibCompileFlags z_zlibCompileFlags
|
||||
# define zlibVersion z_zlibVersion
|
||||
|
||||
|
@ -111,7 +143,9 @@
|
|||
# define alloc_func z_alloc_func
|
||||
# define charf z_charf
|
||||
# define free_func z_free_func
|
||||
# define gzFile z_gzFile
|
||||
# ifndef Z_SOLO
|
||||
# define gzFile z_gzFile
|
||||
# endif
|
||||
# define gz_header z_gz_header
|
||||
# define gz_headerp z_gz_headerp
|
||||
# define in_func z_in_func
|
||||
|
@ -197,9 +231,25 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* Some Mac compilers merge all .h files incorrectly: */
|
||||
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
|
||||
# define NO_DUMMY_DECL
|
||||
#if defined(ZLIB_CONST) && !defined(z_const)
|
||||
# define z_const const
|
||||
#else
|
||||
# define z_const
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
typedef unsigned long z_size_t;
|
||||
#else
|
||||
# define z_longlong long long
|
||||
# if defined(NO_SIZE_T)
|
||||
typedef unsigned NO_SIZE_T z_size_t;
|
||||
# elif defined(STDC)
|
||||
# include <stddef.h>
|
||||
typedef size_t z_size_t;
|
||||
# else
|
||||
typedef unsigned long z_size_t;
|
||||
# endif
|
||||
# undef z_longlong
|
||||
#endif
|
||||
|
||||
/* Maximum value for memLevel in deflateInit2 */
|
||||
|
@ -229,7 +279,7 @@
|
|||
Of course this will generally degrade compression (there's no free lunch).
|
||||
|
||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||
that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
|
||||
for small objects.
|
||||
*/
|
||||
|
||||
|
@ -243,6 +293,14 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef Z_ARG /* function prototypes for stdarg */
|
||||
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# define Z_ARG(args) args
|
||||
# else
|
||||
# define Z_ARG(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||
* model programming (small or medium model with some far allocations).
|
||||
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||
|
@ -356,12 +414,47 @@ typedef uLong FAR uLongf;
|
|||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
|
||||
# include <limits.h>
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned
|
||||
# elif (ULONG_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned long
|
||||
# elif (USHRT_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned short
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef Z_U4
|
||||
typedef Z_U4 z_crc_t;
|
||||
#else
|
||||
typedef unsigned long z_crc_t;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_STDARG_H
|
||||
#endif
|
||||
|
||||
#ifdef STDC
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# ifndef Z_SOLO
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# ifndef Z_SOLO
|
||||
# include <stdarg.h> /* for va_list */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef Z_SOLO
|
||||
# include <stddef.h> /* for wchar_t */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
|
||||
|
@ -370,21 +463,38 @@ typedef uLong FAR uLongf;
|
|||
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
|
||||
* equivalently requesting no 64-bit operations
|
||||
*/
|
||||
#if -_LARGEFILE64_SOURCE - -1 == 1
|
||||
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
|
||||
# undef _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
# include <unistd.h> /* for SEEK_* and off_t */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# ifndef z_off_t
|
||||
# define z_off_t off_t
|
||||
#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
#ifndef Z_SOLO
|
||||
# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# ifndef z_off_t
|
||||
# define z_off_t off_t
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
|
||||
# define Z_LFS64
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
|
||||
# define Z_LARGE64
|
||||
#endif
|
||||
|
||||
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
|
||||
# define Z_WANT64
|
||||
#endif
|
||||
|
||||
#if !defined(SEEK_SET) && !defined(Z_SOLO)
|
||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||
# define SEEK_CUR 1 /* Seek from current position. */
|
||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||
|
@ -394,18 +504,14 @@ typedef uLong FAR uLongf;
|
|||
# define z_off_t long
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
#if !defined(_WIN32) && defined(Z_LARGE64)
|
||||
# define z_off64_t off64_t
|
||||
#else
|
||||
# define z_off64_t z_off_t
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__)
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
# define NO_vsnprintf
|
||||
# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
|
||||
# define z_off64_t __int64
|
||||
# else
|
||||
# define z_off64_t z_off_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* MVS linker does not support external names larger than 8 bytes */
|
||||
|
|
743
src/engine/external/zlib/zlib.h
vendored
71
src/engine/external/zlib/zutil.c
vendored
|
@ -1,27 +1,27 @@
|
|||
/* zutil.c -- target dependent utility functions for the compression library
|
||||
* Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2017 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#ifndef NO_DUMMY_DECL
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
#ifndef Z_SOLO
|
||||
# include "gzguts.h"
|
||||
#endif
|
||||
|
||||
const char * const z_errmsg[10] = {
|
||||
"need dictionary", /* Z_NEED_DICT 2 */
|
||||
"stream end", /* Z_STREAM_END 1 */
|
||||
"", /* Z_OK 0 */
|
||||
"file error", /* Z_ERRNO (-1) */
|
||||
"stream error", /* Z_STREAM_ERROR (-2) */
|
||||
"data error", /* Z_DATA_ERROR (-3) */
|
||||
"insufficient memory", /* Z_MEM_ERROR (-4) */
|
||||
"buffer error", /* Z_BUF_ERROR (-5) */
|
||||
"incompatible version",/* Z_VERSION_ERROR (-6) */
|
||||
""};
|
||||
z_const char * const z_errmsg[10] = {
|
||||
(z_const char *)"need dictionary", /* Z_NEED_DICT 2 */
|
||||
(z_const char *)"stream end", /* Z_STREAM_END 1 */
|
||||
(z_const char *)"", /* Z_OK 0 */
|
||||
(z_const char *)"file error", /* Z_ERRNO (-1) */
|
||||
(z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */
|
||||
(z_const char *)"data error", /* Z_DATA_ERROR (-3) */
|
||||
(z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */
|
||||
(z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */
|
||||
(z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
|
||||
(z_const char *)""
|
||||
};
|
||||
|
||||
|
||||
const char * ZEXPORT zlibVersion()
|
||||
|
@ -58,7 +58,7 @@ uLong ZEXPORT zlibCompileFlags()
|
|||
case 8: flags += 2 << 6; break;
|
||||
default: flags += 3 << 6;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
flags += 1 << 8;
|
||||
#endif
|
||||
#if defined(ASMV) || defined(ASMINF)
|
||||
|
@ -85,35 +85,35 @@ uLong ZEXPORT zlibCompileFlags()
|
|||
#ifdef FASTEST
|
||||
flags += 1L << 21;
|
||||
#endif
|
||||
#ifdef STDC
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# ifdef NO_vsnprintf
|
||||
flags += 1L << 25;
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_vsprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
flags += 1L << 24;
|
||||
flags += 1L << 24;
|
||||
# ifdef NO_snprintf
|
||||
flags += 1L << 25;
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_sprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_snprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifdef ZLIB_DEBUG
|
||||
#include <stdlib.h>
|
||||
# ifndef verbose
|
||||
# define verbose 0
|
||||
# endif
|
||||
|
@ -181,6 +181,7 @@ void ZLIB_INTERNAL zmemzero(dest, len)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef Z_SOLO
|
||||
|
||||
#ifdef SYS16BIT
|
||||
|
||||
|
@ -215,9 +216,11 @@ local ptr_table table[MAX_PTR];
|
|||
|
||||
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
{
|
||||
voidpf buf = opaque; /* just to make some compilers happy */
|
||||
voidpf buf;
|
||||
ulg bsize = (ulg)items*size;
|
||||
|
||||
(void)opaque;
|
||||
|
||||
/* If we allocate less than 65520 bytes, we assume that farmalloc
|
||||
* will return a usable pointer which doesn't have to be normalized.
|
||||
*/
|
||||
|
@ -240,6 +243,9 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
|
|||
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
int n;
|
||||
|
||||
(void)opaque;
|
||||
|
||||
if (*(ush*)&ptr != 0) { /* object < 64K */
|
||||
farfree(ptr);
|
||||
return;
|
||||
|
@ -255,7 +261,6 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
|||
next_ptr--;
|
||||
return;
|
||||
}
|
||||
ptr = opaque; /* just to make some compilers happy */
|
||||
Assert(0, "zcfree: ptr not found");
|
||||
}
|
||||
|
||||
|
@ -274,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
|||
|
||||
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
(void)opaque;
|
||||
return _halloc((long)items, size);
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
(void)opaque;
|
||||
_hfree(ptr);
|
||||
}
|
||||
|
||||
|
@ -302,7 +307,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
|
|||
unsigned items;
|
||||
unsigned size;
|
||||
{
|
||||
if (opaque) items += size - size; /* make compiler happy */
|
||||
(void)opaque;
|
||||
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
|
||||
(voidpf)calloc(items, size);
|
||||
}
|
||||
|
@ -311,8 +316,10 @@ void ZLIB_INTERNAL zcfree (opaque, ptr)
|
|||
voidpf opaque;
|
||||
voidpf ptr;
|
||||
{
|
||||
(void)opaque;
|
||||
free(ptr);
|
||||
if (opaque) return; /* make compiler happy */
|
||||
}
|
||||
|
||||
#endif /* MY_ZCALLOC */
|
||||
|
||||
#endif /* !Z_SOLO */
|
||||
|
|
153
src/engine/external/zlib/zutil.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
|||
#ifndef ZUTIL_H
|
||||
#define ZUTIL_H
|
||||
|
||||
#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef STDC
|
||||
#if defined(STDC) && !defined(Z_SOLO)
|
||||
# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
|
||||
# include <stddef.h>
|
||||
# endif
|
||||
|
@ -29,10 +29,16 @@
|
|||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
/* since "static" is used to mean two completely different things in C, we
|
||||
define "local" for the non-static meaning of "static", for readability
|
||||
(compile with -Dlocal if your debugger can't find static symbols) */
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef uch FAR uchf;
|
||||
|
@ -40,13 +46,13 @@ typedef unsigned short ush;
|
|||
typedef ush FAR ushf;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
/* (size given to avoid silly warnings with Visual C++) */
|
||||
|
||||
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
|
||||
|
||||
#define ERR_RETURN(strm,err) \
|
||||
return (strm->msg = (char*)ERR_MSG(err), (err))
|
||||
return (strm->msg = ERR_MSG(err), (err))
|
||||
/* To be used only when the state is known to be valid */
|
||||
|
||||
/* common constants */
|
||||
|
@ -78,63 +84,83 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
|
||||
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
|
||||
# define OS_CODE 0x00
|
||||
# if defined(__TURBOC__) || defined(__BORLANDC__)
|
||||
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
|
||||
/* Allow compilation with ANSI keywords only enabled */
|
||||
void _Cdecl farfree( void *block );
|
||||
void *_Cdecl farmalloc( unsigned long nbytes );
|
||||
# else
|
||||
# include <alloc.h>
|
||||
# ifndef Z_SOLO
|
||||
# if defined(__TURBOC__) || defined(__BORLANDC__)
|
||||
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
|
||||
/* Allow compilation with ANSI keywords only enabled */
|
||||
void _Cdecl farfree( void *block );
|
||||
void *_Cdecl farmalloc( unsigned long nbytes );
|
||||
# else
|
||||
# include <alloc.h>
|
||||
# endif
|
||||
# else /* MSC or DJGPP */
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
# else /* MSC or DJGPP */
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef AMIGA
|
||||
# define OS_CODE 0x01
|
||||
# define OS_CODE 1
|
||||
#endif
|
||||
|
||||
#if defined(VAXC) || defined(VMS)
|
||||
# define OS_CODE 0x02
|
||||
# define OS_CODE 2
|
||||
# define F_OPEN(name, mode) \
|
||||
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
|
||||
#endif
|
||||
|
||||
#ifdef __370__
|
||||
# if __TARGET_LIB__ < 0x20000000
|
||||
# define OS_CODE 4
|
||||
# elif __TARGET_LIB__ < 0x40000000
|
||||
# define OS_CODE 11
|
||||
# else
|
||||
# define OS_CODE 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ATARI) || defined(atarist)
|
||||
# define OS_CODE 0x05
|
||||
# define OS_CODE 5
|
||||
#endif
|
||||
|
||||
#ifdef OS2
|
||||
# define OS_CODE 0x06
|
||||
# ifdef M_I86
|
||||
# define OS_CODE 6
|
||||
# if defined(M_I86) && !defined(Z_SOLO)
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||
# define OS_CODE 0x07
|
||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fdopen */
|
||||
# else
|
||||
# ifndef fdopen
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# define OS_CODE 7
|
||||
# ifndef Z_SOLO
|
||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fdopen */
|
||||
# else
|
||||
# ifndef fdopen
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef TOPS20
|
||||
# define OS_CODE 0x0a
|
||||
#ifdef __acorn
|
||||
# define OS_CODE 13
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
|
||||
# define OS_CODE 0x0b
|
||||
# endif
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
# define OS_CODE 10
|
||||
#endif
|
||||
|
||||
#ifdef __50SERIES /* Prime/PRIMOS */
|
||||
# define OS_CODE 0x0f
|
||||
#ifdef _BEOS_
|
||||
# define OS_CODE 16
|
||||
#endif
|
||||
|
||||
#ifdef __TOS_OS400__
|
||||
# define OS_CODE 18
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# define OS_CODE 19
|
||||
#endif
|
||||
|
||||
#if defined(_BEOS_) || defined(RISCOS)
|
||||
|
@ -153,14 +179,15 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
#if defined(__BORLANDC__) && !defined(MSDOS)
|
||||
#pragma warn -8004
|
||||
#pragma warn -8008
|
||||
#pragma warn -8066
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
|
||||
#if !defined(_WIN32) && \
|
||||
(!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
|
||||
#endif
|
||||
|
@ -168,7 +195,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
/* common defaults */
|
||||
|
||||
#ifndef OS_CODE
|
||||
# define OS_CODE 0x03 /* assume Unix */
|
||||
# define OS_CODE 3 /* assume Unix */
|
||||
#endif
|
||||
|
||||
#ifndef F_OPEN
|
||||
|
@ -177,42 +204,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
|
||||
/* functions */
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__CYGWIN__)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef MSDOS
|
||||
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||
but for now we just assume it doesn't. */
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
#ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(pyr)
|
||||
#if defined(pyr) || defined(Z_SOLO)
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
|
||||
|
@ -242,7 +234,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
#endif
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
#ifdef ZLIB_DEBUG
|
||||
# include <stdio.h>
|
||||
extern int ZLIB_INTERNAL z_verbose;
|
||||
extern void ZLIB_INTERNAL z_error OF((char *m));
|
||||
|
@ -261,14 +253,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
|
||||
unsigned size));
|
||||
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
|
||||
#ifndef Z_SOLO
|
||||
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
|
||||
unsigned size));
|
||||
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
|
||||
#endif
|
||||
|
||||
#define ZALLOC(strm, items, size) \
|
||||
(*((strm)->zalloc))((strm)->opaque, (items), (size))
|
||||
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
|
||||
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
|
||||
|
||||
/* Reverse the bytes in a 32-bit value */
|
||||
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
|
||||
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
|
||||
|
||||
#endif /* ZUTIL_H */
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
TEXLOAD_NOMIPMAPS = 2,
|
||||
TEXLOAD_ARRAY_256 = 4,
|
||||
TEXLOAD_MULTI_DIMENSION = 8,
|
||||
TEXLOAD_LINEARMIPMAPS = 16,
|
||||
};
|
||||
|
||||
/* Constants: Wrap Modes */
|
||||
|
|
|
@ -266,6 +266,7 @@ int CRegister::RegisterProcessPacket(CNetChunk *pPacket, TOKEN Token)
|
|||
if(m_RegisterFirst && m_RegisterState != REGISTERSTATE_REGISTERED)
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", "no firewall/nat problems detected");
|
||||
RegisterNewState(REGISTERSTATE_REGISTERED);
|
||||
m_pNetServer->AddToken(&pPacket->m_Address, Token);
|
||||
return 1;
|
||||
}
|
||||
else if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWERROR) &&
|
||||
|
|
|
@ -886,6 +886,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
{
|
||||
CClient::CInput *pInput;
|
||||
int64 TagTime;
|
||||
int64 Now = time_get();
|
||||
|
||||
m_aClients[ClientID].m_LastAckedSnapshot = Unpacker.GetInt();
|
||||
int IntendedTick = Unpacker.GetInt();
|
||||
|
@ -898,14 +899,11 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
if(m_aClients[ClientID].m_LastAckedSnapshot > 0)
|
||||
m_aClients[ClientID].m_SnapRate = CClient::SNAPRATE_FULL;
|
||||
|
||||
if(m_aClients[ClientID].m_Snapshots.Get(m_aClients[ClientID].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0)
|
||||
m_aClients[ClientID].m_Latency = (int)(((time_get()-TagTime)*1000)/time_freq());
|
||||
|
||||
// add message to report the input timing
|
||||
// skip packets that are old
|
||||
if(IntendedTick > m_aClients[ClientID].m_LastInputTick)
|
||||
{
|
||||
int TimeLeft = ((TickStartTime(IntendedTick)-time_get())*1000) / time_freq();
|
||||
int TimeLeft = ((TickStartTime(IntendedTick)-Now)*1000) / time_freq();
|
||||
|
||||
CMsgPacker Msg(NETMSG_INPUTTIMING, true);
|
||||
Msg.AddInt(IntendedTick);
|
||||
|
@ -925,6 +923,13 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
|
|||
for(int i = 0; i < Size/4; i++)
|
||||
pInput->m_aData[i] = Unpacker.GetInt();
|
||||
|
||||
int PingCorrection = clamp(Unpacker.GetInt(), 0, 50);
|
||||
if(m_aClients[ClientID].m_Snapshots.Get(m_aClients[ClientID].m_LastAckedSnapshot, &TagTime, 0, 0) >= 0)
|
||||
{
|
||||
m_aClients[ClientID].m_Latency = (int)(((Now-TagTime)*1000)/time_freq());
|
||||
m_aClients[ClientID].m_Latency = max(0, m_aClients[ClientID].m_Latency - PingCorrection);
|
||||
}
|
||||
|
||||
mem_copy(m_aClients[ClientID].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE*sizeof(int));
|
||||
|
||||
m_aClients[ClientID].m_CurrentInput++;
|
||||
|
@ -1095,7 +1100,7 @@ void CServer::GenerateServerInfo(CPacker *pPacker, int Token)
|
|||
pPacker->AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan
|
||||
pPacker->AddInt(m_aClients[i].m_Country); // client country
|
||||
pPacker->AddInt(m_aClients[i].m_Score); // client score
|
||||
pPacker->AddInt(GameServer()->IsClientPlayer(i)?1:0); // is player?
|
||||
pPacker->AddInt(GameServer()->IsClientPlayer(i)?0:1); // flag spectator=1, bot=2 (player=0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,16 @@ public:
|
|||
char m_aClan[MAX_CLAN_LENGTH];
|
||||
int m_Country;
|
||||
int m_Score;
|
||||
bool m_Player;
|
||||
int m_PlayerType;
|
||||
|
||||
int m_FriendState;
|
||||
|
||||
enum
|
||||
{
|
||||
PLAYERFLAG_SPEC=1,
|
||||
PLAYERFLAG_BOT=2,
|
||||
PLAYERFLAG_MASK=3,
|
||||
};
|
||||
};
|
||||
|
||||
//int m_SortedIndex;
|
||||
|
@ -40,6 +47,8 @@ public:
|
|||
int m_NumClients;
|
||||
int m_MaxPlayers;
|
||||
int m_NumPlayers;
|
||||
int m_NumBotPlayers;
|
||||
int m_NumBotSpectators;
|
||||
int m_Flags;
|
||||
int m_ServerLevel;
|
||||
int m_Favorite;
|
||||
|
@ -56,10 +65,15 @@ public:
|
|||
class CServerFilterInfo
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_GAMETYPES=8,
|
||||
};
|
||||
int m_SortHash;
|
||||
int m_Ping;
|
||||
int m_Country;
|
||||
char m_aGametype[16];
|
||||
int m_ServerLevel;
|
||||
char m_aGametype[MAX_GAMETYPES][16];
|
||||
char m_aAddress[NETADDR_MAXSTRSIZE];
|
||||
};
|
||||
|
||||
|
@ -97,6 +111,7 @@ public:
|
|||
FLAG_PURE=2,
|
||||
FLAG_PUREMAP=4,
|
||||
|
||||
FILTER_BOTS=16,
|
||||
FILTER_EMPTY=32,
|
||||
FILTER_FULL=64,
|
||||
FILTER_SPECTATORS=128,
|
||||
|
@ -106,9 +121,8 @@ public:
|
|||
FILTER_COMPAT_VERSION=2048,
|
||||
FILTER_PURE=4096,
|
||||
FILTER_PURE_MAP=8192,
|
||||
FILTER_GAMETYPE_STRICT=16384,
|
||||
FILTER_COUNTRY=32768,
|
||||
FILTER_PING=65536,
|
||||
FILTER_COUNTRY= 16384,
|
||||
FILTER_PING= 32768,
|
||||
};
|
||||
|
||||
virtual void SetType(int Type) = 0;
|
||||
|
@ -119,6 +133,8 @@ public:
|
|||
|
||||
virtual int NumServers() const = 0;
|
||||
virtual int NumPlayers() const = 0;
|
||||
virtual int NumClients() const = 0;
|
||||
virtual const CServerInfo *Get(int Index) const = 0;
|
||||
|
||||
virtual int NumSortedServers(int Index) const = 0;
|
||||
virtual int NumSortedPlayers(int Index) const = 0;
|
||||
|
|
|
@ -34,11 +34,11 @@ MACRO_CONFIG_INT(BrMaxRequests, br_max_requests, 25, 0, 1000, CFGFLAG_SAVE|CFGFL
|
|||
|
||||
MACRO_CONFIG_INT(SndBufferSize, snd_buffer_size, 512, 128, 32768, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound buffer size")
|
||||
MACRO_CONFIG_INT(SndRate, snd_rate, 48000, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound mixing rate")
|
||||
MACRO_CONFIG_INT(SndEnable, snd_enable, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound enable")
|
||||
MACRO_CONFIG_INT(SndEnable, snd_enable, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Enable sounds")
|
||||
MACRO_CONFIG_INT(SndInit, snd_init, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Initialize sound systems")
|
||||
MACRO_CONFIG_INT(SndMusic, snd_enable_music, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Play background music")
|
||||
MACRO_CONFIG_INT(SndVolume, snd_volume, 100, 0, 100, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Sound volume")
|
||||
MACRO_CONFIG_INT(SndDevice, snd_device, -1, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "(deprecated) Sound device to use")
|
||||
|
||||
MACRO_CONFIG_INT(SndNonactiveMute, snd_nonactive_mute, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
|
||||
|
||||
MACRO_CONFIG_INT(GfxScreen, gfx_screen, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen index")
|
||||
|
|
|
@ -97,14 +97,15 @@ void CNetBase::SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN
|
|||
dbg_assert((ResponseToken&~NET_TOKEN_MASK) == 0, "resp token out of range");
|
||||
|
||||
int i = 0;
|
||||
aBuffer[i++] = (Token>>12)&0xff; // token
|
||||
aBuffer[i++] = (Token>>4)&0xff;
|
||||
aBuffer[i++] = ((Token&0xf)<<4)
|
||||
| (NET_PACKETFLAG_CONNLESS&0xf); // connless flag
|
||||
aBuffer[i++] = ((NET_PACKETVERSION&0x0f)<<4) // version
|
||||
| ((ResponseToken>>16)&0xf); // response token
|
||||
aBuffer[i++] = ((NET_PACKETFLAG_CONNLESS<<2)&0xfc) | (NET_PACKETVERSION&0x03); // connless flag and version
|
||||
aBuffer[i++] = (Token>>24)&0xff; // token
|
||||
aBuffer[i++] = (Token>>16)&0xff;
|
||||
aBuffer[i++] = (Token>>8)&0xff;
|
||||
aBuffer[i++] = (Token)&0xff;
|
||||
aBuffer[i++] = (ResponseToken>>24)&0xff; // response token
|
||||
aBuffer[i++] = (ResponseToken>>16)&0xff;
|
||||
aBuffer[i++] = (ResponseToken>>8)&0xff;
|
||||
aBuffer[i++] = ResponseToken&0xff;
|
||||
aBuffer[i++] = (ResponseToken)&0xff;
|
||||
|
||||
dbg_assert(i == NET_PACKETHEADERSIZE_CONNLESS, "inconsistency");
|
||||
|
||||
|
@ -154,13 +155,13 @@ void CNetBase::SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketCons
|
|||
FinalSize += NET_PACKETHEADERSIZE;
|
||||
|
||||
int i = 0;
|
||||
aBuffer[i++] = (pPacket->m_Token>>12)&0xff; // token
|
||||
aBuffer[i++] = (pPacket->m_Token>>4)&0xff;
|
||||
aBuffer[i++] = ((pPacket->m_Token<<4)&0xf0)
|
||||
| ((pPacket->m_Flags)&0xf); // flags
|
||||
aBuffer[i++] = (pPacket->m_Ack>>2)&0xff; // ack
|
||||
aBuffer[i++] = ((pPacket->m_Ack<<6)&0xc0)
|
||||
| (pPacket->m_NumChunks&0x3f);
|
||||
aBuffer[i++] = ((pPacket->m_Flags<<2)&0xfc) | ((pPacket->m_Ack>>8)&0x03); // flags and ack
|
||||
aBuffer[i++] = (pPacket->m_Ack)&0xff; // ack
|
||||
aBuffer[i++] = (pPacket->m_NumChunks)&0xff; // num chunks
|
||||
aBuffer[i++] = (pPacket->m_Token>>24)&0xff; // token
|
||||
aBuffer[i++] = (pPacket->m_Token>>16)&0xff;
|
||||
aBuffer[i++] = (pPacket->m_Token>>8)&0xff;
|
||||
aBuffer[i++] = (pPacket->m_Token)&0xff;
|
||||
|
||||
dbg_assert(i == NET_PACKETHEADERSIZE, "inconsistency");
|
||||
|
||||
|
@ -200,11 +201,9 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
}
|
||||
|
||||
// read the packet
|
||||
pPacket->m_Token = (pBuffer[0]<<12) | (pBuffer[1]<<4) | (pBuffer[2]>>4);
|
||||
// TTTTTTTT TTTTTTTT TTTTxxxx
|
||||
pPacket->m_Flags = pBuffer[2]&0x0f;
|
||||
// xxxxFFFF
|
||||
|
||||
pPacket->m_Flags = (pBuffer[0]&0xfc)>>2;
|
||||
// FFFFFFxx
|
||||
if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS)
|
||||
{
|
||||
if(Size < NET_PACKETHEADERSIZE_CONNLESS)
|
||||
|
@ -217,15 +216,17 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
pPacket->m_Flags = NET_PACKETFLAG_CONNLESS;
|
||||
pPacket->m_Ack = 0;
|
||||
pPacket->m_NumChunks = 0;
|
||||
int Version = (pBuffer[3]>>4);
|
||||
// VVVVxxxx
|
||||
int Version = pBuffer[0]&0x3;
|
||||
// xxxxxxVV
|
||||
|
||||
if(Version != NET_PACKETVERSION)
|
||||
return -1;
|
||||
|
||||
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE_CONNLESS;
|
||||
pPacket->m_ResponseToken = ((pBuffer[3]&0x0f)<<16) | (pBuffer[4]<<8) | pBuffer[5];
|
||||
// xxxxRRRR RRRRRRRR RRRRRRRR
|
||||
pPacket->m_Token = (pBuffer[1] << 24) | (pBuffer[2] << 16) | (pBuffer[3] << 8) | pBuffer[4];
|
||||
// TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT
|
||||
pPacket->m_ResponseToken = (pBuffer[5]<<24) | (pBuffer[6]<<16) | (pBuffer[7]<<8) | pBuffer[8];
|
||||
// RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR
|
||||
mem_copy(pPacket->m_aChunkData, &pBuffer[NET_PACKETHEADERSIZE_CONNLESS], pPacket->m_DataSize);
|
||||
}
|
||||
else
|
||||
|
@ -237,12 +238,14 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
return -1;
|
||||
}
|
||||
|
||||
pPacket->m_Ack = (pBuffer[3]<<2) | ((pBuffer[4]&0xc0)>>6);
|
||||
// AAAAAAAA AAxxxxxx
|
||||
pPacket->m_NumChunks = pBuffer[4]&0x3f;
|
||||
// xxNNNNNN
|
||||
pPacket->m_Ack = ((pBuffer[0]&0x3)<<8) | pBuffer[1];
|
||||
// xxxxxxAA AAAAAAAA
|
||||
pPacket->m_NumChunks = pBuffer[2];
|
||||
// NNNNNNNN
|
||||
|
||||
pPacket->m_DataSize = Size - NET_PACKETHEADERSIZE;
|
||||
pPacket->m_Token = (pBuffer[3] << 24) | (pBuffer[4] << 16) | (pBuffer[5] << 8) | pBuffer[6];
|
||||
// TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT
|
||||
pPacket->m_ResponseToken = NET_TOKEN_NONE;
|
||||
|
||||
if(pPacket->m_Flags&NET_PACKETFLAG_COMPRESSION)
|
||||
|
@ -262,13 +265,13 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct
|
|||
// set the response token (a bit hacky because this function shouldn't know about control packets)
|
||||
if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)
|
||||
{
|
||||
if(pPacket->m_DataSize >= 4) // control byte + token
|
||||
if(pPacket->m_DataSize >= 5) // control byte + token
|
||||
{
|
||||
if(pPacket->m_aChunkData[0] == NET_CTRLMSG_CONNECT
|
||||
|| pPacket->m_aChunkData[0] == NET_CTRLMSG_TOKEN)
|
||||
{
|
||||
pPacket->m_ResponseToken = ((pPacket->m_aChunkData[1]&0xf)<<16)
|
||||
| (pPacket->m_aChunkData[2]<<8) | pPacket->m_aChunkData[3];
|
||||
pPacket->m_ResponseToken = (pPacket->m_aChunkData[1]<<24) | (pPacket->m_aChunkData[2]<<16)
|
||||
| (pPacket->m_aChunkData[3]<<8) | pPacket->m_aChunkData[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,17 +307,17 @@ void CNetBase::SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Toke
|
|||
}
|
||||
|
||||
|
||||
void CNetBase::SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken)
|
||||
void CNetBase::SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended)
|
||||
{
|
||||
dbg_assert((Token&~NET_TOKEN_MASK) == 0, "token out of range");
|
||||
dbg_assert((MyToken&~NET_TOKEN_MASK) == 0, "resp token out of range");
|
||||
|
||||
unsigned char aToken[3];
|
||||
aToken[0] = (MyToken>>16)&0xff;
|
||||
aToken[1] = (MyToken>>8)&0xff;
|
||||
aToken[2] = (MyToken)&0xff;
|
||||
|
||||
SendControlMsg(Socket, pAddr, Token, 0, ControlMsg, aToken, sizeof(aToken));
|
||||
static unsigned char aBuf[NET_TOKENREQUEST_DATASIZE] = { 0 };
|
||||
aBuf[0] = (MyToken>>24)&0xff;
|
||||
aBuf[1] = (MyToken>>16)&0xff;
|
||||
aBuf[2] = (MyToken>>8)&0xff;
|
||||
aBuf[3] = (MyToken)&0xff;
|
||||
SendControlMsg(Socket, pAddr, Token, 0, ControlMsg, aBuf, Extended ? sizeof(aBuf) : 4);
|
||||
}
|
||||
|
||||
unsigned char *CNetChunkHeader::Pack(unsigned char *pData)
|
||||
|
|
|
@ -9,32 +9,36 @@
|
|||
/*
|
||||
|
||||
CURRENT:
|
||||
packet header: 5 bytes (6 bytes for connless)
|
||||
unsigned char token[2]; // 16bit token
|
||||
unsigned char token_flags; // 4bit token, 4bit flags
|
||||
unsigned char ack; // 8bit ack
|
||||
unsigned char ack_numchunks; // 2bit ack, 6bit chunks
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// TTTTffff
|
||||
packet header: 7 bytes (9 bytes for connless)
|
||||
unsigned char flags_ack; // 6bit flags, 2bit ack
|
||||
unsigned char ack; // 8bit ack
|
||||
unsigned char numchunks; // 8bit chunks
|
||||
unsigned char token[4]; // 32bit token
|
||||
// ffffffaa
|
||||
// aaaaaaaa
|
||||
// aaNNNNNN
|
||||
// NNNNNNNN
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
|
||||
packet header (CONNLESS):
|
||||
unsigned char token[2]; // 16bit token
|
||||
unsigned char token_flag; // 4bit token, 4bit flags
|
||||
unsigned char version_responsetoken; // 4bit version, 4bit response token
|
||||
unsigned char responsetoken[2]; // 16bit response token
|
||||
unsigned char flag_version; // 6bit flags, 2bits version
|
||||
unsigned char token[4]; // 32bit token
|
||||
unsigned char responsetoken[4]; // 32bit response token
|
||||
|
||||
// ffffffvv
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// TTTTffff
|
||||
// vvvvRRRR
|
||||
// TTTTTTTT
|
||||
// TTTTTTTT
|
||||
// RRRRRRRR
|
||||
// RRRRRRRR
|
||||
// RRRRRRRR
|
||||
// RRRRRRRR
|
||||
|
||||
if the token isn't explicitely set by any means, it must be set to
|
||||
0xfffff
|
||||
0xffffffff
|
||||
|
||||
chunk header: 2-3 bytes
|
||||
unsigned char flags_size; // 2bit flags, 6 bit size
|
||||
|
@ -62,13 +66,11 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
NET_VERSION = 2,
|
||||
|
||||
NET_MAX_CHUNKHEADERSIZE = 3,
|
||||
|
||||
// packets
|
||||
NET_PACKETHEADERSIZE = 5,
|
||||
NET_PACKETHEADERSIZE_CONNLESS = NET_PACKETHEADERSIZE + 1,
|
||||
NET_PACKETHEADERSIZE = 7,
|
||||
NET_PACKETHEADERSIZE_CONNLESS = NET_PACKETHEADERSIZE + 2,
|
||||
NET_MAX_PACKETHEADERSIZE = NET_PACKETHEADERSIZE_CONNLESS,
|
||||
|
||||
NET_MAX_PACKETSIZE = 1400,
|
||||
|
@ -81,16 +83,27 @@ enum
|
|||
NET_PACKETFLAG_COMPRESSION=4,
|
||||
NET_PACKETFLAG_CONNLESS=8,
|
||||
|
||||
NET_MAX_PACKET_CHUNKS=256,
|
||||
|
||||
// token
|
||||
NET_SEEDTIME = 10,
|
||||
NET_SEEDTIME = 16,
|
||||
|
||||
NET_TOKENCACHE_SIZE = 16,
|
||||
NET_TOKENCACHE_ADDRESSEXPIRY = NET_SEEDTIME/2,
|
||||
NET_TOKENCACHE_PACKETEXPIRY = NET_TOKENCACHE_ADDRESSEXPIRY,
|
||||
|
||||
NET_TOKEN_MAX = 0xfffff,
|
||||
NET_TOKENCACHE_SIZE = 64,
|
||||
NET_TOKENCACHE_ADDRESSEXPIRY = NET_SEEDTIME,
|
||||
NET_TOKENCACHE_PACKETEXPIRY = 5,
|
||||
};
|
||||
enum
|
||||
{
|
||||
NET_TOKEN_MAX = 0xffffffff,
|
||||
NET_TOKEN_NONE = NET_TOKEN_MAX,
|
||||
NET_TOKEN_MASK = NET_TOKEN_MAX,
|
||||
};
|
||||
enum
|
||||
{
|
||||
NET_TOKENFLAG_ALLOWBROADCAST = 1,
|
||||
NET_TOKENFLAG_RESPONSEONLY = 2,
|
||||
|
||||
NET_TOKENREQUEST_DATASIZE = 512,
|
||||
|
||||
//
|
||||
NET_MAX_CLIENTS = 16,
|
||||
|
@ -182,9 +195,9 @@ public:
|
|||
|
||||
void GenerateSeed();
|
||||
|
||||
int ProcessMessage(const NETADDR *pAddr, const CNetPacketConstruct *pPacket, bool Notify);
|
||||
int ProcessMessage(const NETADDR *pAddr, const CNetPacketConstruct *pPacket);
|
||||
|
||||
bool CheckToken(const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, bool Notify);
|
||||
bool CheckToken(const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, bool *BroadcastResponse);
|
||||
TOKEN GenerateToken(const NETADDR *pAddr) const;
|
||||
static TOKEN GenerateToken(const NETADDR *pAddr, int64 Seed);
|
||||
|
||||
|
@ -201,6 +214,13 @@ private:
|
|||
int64 m_NextSeedTime;
|
||||
};
|
||||
|
||||
typedef void(*FSendCallback)(int TrackID, void *pUser);
|
||||
struct CSendCBData
|
||||
{
|
||||
FSendCallback m_pfnCallback;
|
||||
void *m_pCallbackUser;
|
||||
int m_TrackID;
|
||||
};
|
||||
|
||||
class CNetTokenCache
|
||||
{
|
||||
|
@ -208,20 +228,30 @@ public:
|
|||
CNetTokenCache();
|
||||
~CNetTokenCache();
|
||||
void Init(NETSOCKET Socket, const CNetTokenManager *pTokenManager);
|
||||
void SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize);
|
||||
void SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize, CSendCBData *pCallbackData = 0);
|
||||
void PurgeStoredPacket(int TrackID);
|
||||
void FetchToken(const NETADDR *pAddr);
|
||||
void AddToken(const NETADDR *pAddr, TOKEN PeerToken);
|
||||
void AddToken(const NETADDR *pAddr, TOKEN PeerToken, int TokenFlag);
|
||||
TOKEN GetToken(const NETADDR *pAddr);
|
||||
void Update();
|
||||
|
||||
private:
|
||||
struct CConnlessPacketInfo
|
||||
class CConnlessPacketInfo
|
||||
{
|
||||
private:
|
||||
static int m_UniqueID;
|
||||
|
||||
public:
|
||||
CConnlessPacketInfo() : m_TrackID(CConnlessPacketInfo::m_UniqueID++) {}
|
||||
|
||||
NETADDR m_Addr;
|
||||
int m_DataSize;
|
||||
char m_aData[NET_MAX_PAYLOAD];
|
||||
int64 m_Expiry;
|
||||
|
||||
int64 m_LastTokenRequest;
|
||||
const int m_TrackID;
|
||||
FSendCallback m_pfnCallback;
|
||||
void *m_pCallbackUser;
|
||||
CConnlessPacketInfo *m_pNext;
|
||||
};
|
||||
|
||||
|
@ -406,6 +436,7 @@ public:
|
|||
int Recv(CNetChunk *pChunk, TOKEN *pResponseToken = 0);
|
||||
int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE);
|
||||
int Update();
|
||||
void AddToken(const NETADDR *pAddr, TOKEN Token) { m_TokenCache.AddToken(pAddr, Token, 0); };
|
||||
|
||||
//
|
||||
int Drop(int ClientID, const char *pReason);
|
||||
|
@ -483,7 +514,8 @@ public:
|
|||
|
||||
// communication
|
||||
int Recv(CNetChunk *pChunk, TOKEN *pResponseToken = 0);
|
||||
int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE);
|
||||
int Send(CNetChunk *pChunk, TOKEN Token = NET_TOKEN_NONE, CSendCBData *pCallbackData = 0);
|
||||
void PurgeStoredPacket(int TrackID);
|
||||
|
||||
// pumping
|
||||
int Update();
|
||||
|
@ -514,7 +546,7 @@ public:
|
|||
static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize);
|
||||
|
||||
static void SendControlMsg(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, const void *pExtra, int ExtraSize);
|
||||
static void SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken);
|
||||
static void SendControlMsgWithToken(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, int Ack, int ControlMsg, TOKEN MyToken, bool Extended);
|
||||
static void SendPacketConnless(NETSOCKET Socket, const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, const void *pData, int DataSize);
|
||||
static void SendPacket(NETSOCKET Socket, const NETADDR *pAddr, CNetPacketConstruct *pPacket);
|
||||
static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket);
|
||||
|
|
|
@ -90,16 +90,16 @@ int CNetClient::Recv(CNetChunk *pChunk, TOKEN *pResponseToken)
|
|||
}
|
||||
else
|
||||
{
|
||||
int Accept = m_TokenManager.ProcessMessage(&Addr, &m_RecvUnpacker.m_Data, true);
|
||||
int Accept = m_TokenManager.ProcessMessage(&Addr, &m_RecvUnpacker.m_Data);
|
||||
if(!Accept)
|
||||
continue;
|
||||
|
||||
if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL)
|
||||
{
|
||||
if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_TOKEN)
|
||||
m_TokenCache.AddToken(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken);
|
||||
m_TokenCache.AddToken(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, NET_TOKENFLAG_ALLOWBROADCAST|NET_TOKENFLAG_RESPONSEONLY);
|
||||
}
|
||||
else if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS)
|
||||
else if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS && Accept != -1)
|
||||
{
|
||||
pChunk->m_Flags = NETSENDFLAG_CONNLESS;
|
||||
pChunk->m_ClientID = -1;
|
||||
|
@ -117,7 +117,7 @@ int CNetClient::Recv(CNetChunk *pChunk, TOKEN *pResponseToken)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CNetClient::Send(CNetChunk *pChunk, TOKEN Token)
|
||||
int CNetClient::Send(CNetChunk *pChunk, TOKEN Token, CSendCBData *pCallbackData)
|
||||
{
|
||||
if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ int CNetClient::Send(CNetChunk *pChunk, TOKEN Token)
|
|||
{
|
||||
if(pChunk->m_ClientID == -1)
|
||||
{
|
||||
m_TokenCache.SendPacketConnless(&pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize);
|
||||
m_TokenCache.SendPacketConnless(&pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize, pCallbackData);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -173,6 +173,11 @@ int CNetClient::Send(CNetChunk *pChunk, TOKEN Token)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void CNetClient::PurgeStoredPacket(int TrackID)
|
||||
{
|
||||
m_TokenCache.PurgeStoredPacket(TrackID);
|
||||
}
|
||||
|
||||
int CNetClient::State() const
|
||||
{
|
||||
if(m_Connection.State() == NET_CONNSTATE_ONLINE)
|
||||
|
|
|
@ -108,7 +108,7 @@ int CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, int
|
|||
unsigned char *pChunkData;
|
||||
|
||||
// check if we have space for it, if not, flush the connection
|
||||
if(m_Construct.m_DataSize + DataSize + NET_MAX_CHUNKHEADERSIZE > (int)sizeof(m_Construct.m_aChunkData))
|
||||
if(m_Construct.m_DataSize + DataSize + NET_MAX_CHUNKHEADERSIZE > (int)sizeof(m_Construct.m_aChunkData) || m_Construct.m_NumChunks == NET_MAX_PACKET_CHUNKS)
|
||||
Flush();
|
||||
|
||||
// pack all the data
|
||||
|
@ -174,7 +174,7 @@ void CNetConnection::SendPacketConnless(const char *pData, int DataSize)
|
|||
void CNetConnection::SendControlWithToken(int ControlMsg)
|
||||
{
|
||||
m_LastSendTime = time_get();
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, &m_PeerAddr, m_PeerToken, 0, ControlMsg, m_Token);
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, &m_PeerAddr, m_PeerToken, 0, ControlMsg, m_Token, true);
|
||||
}
|
||||
|
||||
void CNetConnection::ResendChunk(CNetChunkResend *pResend)
|
||||
|
|
|
@ -159,12 +159,12 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken)
|
|||
if(Found)
|
||||
continue;
|
||||
|
||||
int Accept = m_TokenManager.ProcessMessage(&Addr, &m_RecvUnpacker.m_Data, true);
|
||||
int Accept = m_TokenManager.ProcessMessage(&Addr, &m_RecvUnpacker.m_Data);
|
||||
if(Accept <= 0)
|
||||
continue;
|
||||
|
||||
if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL)
|
||||
{
|
||||
if(!Accept)
|
||||
continue;
|
||||
if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT)
|
||||
{
|
||||
bool Found = false;
|
||||
|
@ -199,7 +199,6 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken)
|
|||
Found = true;
|
||||
m_aSlots[i].m_Connection.SetToken(m_RecvUnpacker.m_Data.m_Token);
|
||||
m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr);
|
||||
m_aSlots[i].m_Connection.SetToken(m_RecvUnpacker.m_Data.m_Token); // HACK!
|
||||
if(m_pfnNewClient)
|
||||
m_pfnNewClient(i, m_UserPtr);
|
||||
break;
|
||||
|
@ -213,12 +212,10 @@ int CNetServer::Recv(CNetChunk *pChunk, TOKEN *pResponseToken)
|
|||
}
|
||||
}
|
||||
else if(m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_TOKEN)
|
||||
m_TokenCache.AddToken(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken);
|
||||
m_TokenCache.AddToken(&Addr, m_RecvUnpacker.m_Data.m_ResponseToken, NET_TOKENFLAG_RESPONSEONLY);
|
||||
}
|
||||
else if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONNLESS)
|
||||
{
|
||||
if(Accept <= 0)
|
||||
continue;
|
||||
pChunk->m_Flags = NETSENDFLAG_CONNLESS;
|
||||
pChunk->m_ClientID = -1;
|
||||
pChunk->m_Address = Addr;
|
||||
|
|
|
@ -20,6 +20,8 @@ static unsigned int Hash(char *pData, int Size)
|
|||
return (aDigest[0] ^ aDigest[1] ^ aDigest[2] ^ aDigest[3]);
|
||||
}
|
||||
|
||||
int CNetTokenCache::CConnlessPacketInfo::m_UniqueID = 0;
|
||||
|
||||
void CNetTokenManager::Init(NETSOCKET Socket, int SeedTime)
|
||||
{
|
||||
m_Socket = Socket;
|
||||
|
@ -33,10 +35,11 @@ void CNetTokenManager::Update()
|
|||
GenerateSeed();
|
||||
}
|
||||
|
||||
int CNetTokenManager::ProcessMessage(const NETADDR *pAddr, const CNetPacketConstruct *pPacket, bool Notify)
|
||||
int CNetTokenManager::ProcessMessage(const NETADDR *pAddr, const CNetPacketConstruct *pPacket)
|
||||
{
|
||||
bool BroadcastResponse = false;
|
||||
if(pPacket->m_Token != NET_TOKEN_NONE
|
||||
&& !CheckToken(pAddr, pPacket->m_Token, pPacket->m_ResponseToken, Notify))
|
||||
&& !CheckToken(pAddr, pPacket->m_Token, pPacket->m_ResponseToken, &BroadcastResponse))
|
||||
return 0; // wrong token, silent ignore
|
||||
|
||||
bool Verified = pPacket->m_Token != NET_TOKEN_NONE;
|
||||
|
@ -44,11 +47,11 @@ int CNetTokenManager::ProcessMessage(const NETADDR *pAddr, const CNetPacketConst
|
|||
&& pPacket->m_aChunkData[0] == NET_CTRLMSG_TOKEN;
|
||||
|
||||
if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS)
|
||||
return (Verified) ? 1 : 0; // connless packets without token are not allowed
|
||||
return (Verified && !BroadcastResponse) ? 1 : 0; // connless packets without token are not allowed
|
||||
|
||||
if(!TokenMessage)
|
||||
{
|
||||
if(Verified)
|
||||
if(Verified && !BroadcastResponse)
|
||||
return 1; // verified packet
|
||||
else
|
||||
// the only allowed not connless packet
|
||||
|
@ -57,12 +60,15 @@ int CNetTokenManager::ProcessMessage(const NETADDR *pAddr, const CNetPacketConst
|
|||
}
|
||||
|
||||
if(Verified && TokenMessage)
|
||||
return 1; // everything is fine, token exchange complete
|
||||
return BroadcastResponse ? -1 : 1; // everything is fine, token exchange complete
|
||||
|
||||
// client requesting token
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
||||
pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN,
|
||||
GenerateToken(pAddr));
|
||||
if(pPacket->m_DataSize >= NET_TOKENREQUEST_DATASIZE)
|
||||
{
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
||||
pPacket->m_ResponseToken, 0, NET_CTRLMSG_TOKEN,
|
||||
GenerateToken(pAddr), false);
|
||||
}
|
||||
return 0; // no need to process NET_CTRLMSG_TOKEN further
|
||||
}
|
||||
|
||||
|
@ -93,7 +99,7 @@ TOKEN CNetTokenManager::GenerateToken(const NETADDR *pAddr, int64 Seed)
|
|||
static const NETADDR NullAddr = { 0 };
|
||||
NETADDR Addr;
|
||||
char aBuf[sizeof(NETADDR) + sizeof(int64)];
|
||||
int Result;
|
||||
unsigned int Result;
|
||||
|
||||
if(pAddr->type & NETTYPE_LINK_BROADCAST)
|
||||
return GenerateToken(&NullAddr, Seed);
|
||||
|
@ -110,7 +116,7 @@ TOKEN CNetTokenManager::GenerateToken(const NETADDR *pAddr, int64 Seed)
|
|||
return Result;
|
||||
}
|
||||
|
||||
bool CNetTokenManager::CheckToken(const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, bool Notify)
|
||||
bool CNetTokenManager::CheckToken(const NETADDR *pAddr, TOKEN Token, TOKEN ResponseToken, bool *BroadcastResponse)
|
||||
{
|
||||
TOKEN CurrentToken = GenerateToken(pAddr, m_Seed);
|
||||
if(CurrentToken == Token)
|
||||
|
@ -118,20 +124,18 @@ bool CNetTokenManager::CheckToken(const NETADDR *pAddr, TOKEN Token, TOKEN Respo
|
|||
|
||||
if(GenerateToken(pAddr, m_PrevSeed) == Token)
|
||||
{
|
||||
if(Notify)
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
||||
ResponseToken, 0, NET_CTRLMSG_TOKEN, CurrentToken);
|
||||
// notify the peer about the new token
|
||||
// no need to notify the peer, just a one time thing
|
||||
return true;
|
||||
}
|
||||
else if(Token == m_GlobalToken)
|
||||
{
|
||||
*BroadcastResponse = true;
|
||||
return true;
|
||||
}
|
||||
else if(Token == m_PrevGlobalToken)
|
||||
{
|
||||
if(Notify)
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, (NETADDR *)pAddr,
|
||||
ResponseToken, 0, NET_CTRLMSG_TOKEN, m_GlobalToken);
|
||||
// notify the peer about the new token
|
||||
// no need to notify the peer, just a broadcast token response
|
||||
*BroadcastResponse = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -167,7 +171,7 @@ void CNetTokenCache::Init(NETSOCKET Socket, const CNetTokenManager *pTokenManage
|
|||
m_pTokenManager = pTokenManager;
|
||||
}
|
||||
|
||||
void CNetTokenCache::SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize)
|
||||
void CNetTokenCache::SendPacketConnless(const NETADDR *pAddr, const void *pData, int DataSize, CSendCBData *pCallbackData)
|
||||
{
|
||||
TOKEN Token = GetToken(pAddr);
|
||||
if(Token != NET_TOKEN_NONE)
|
||||
|
@ -187,8 +191,50 @@ void CNetTokenCache::SendPacketConnless(const NETADDR *pAddr, const void *pData,
|
|||
mem_copy((*ppInfo)->m_aData, pData, DataSize);
|
||||
(*ppInfo)->m_Addr = *pAddr;
|
||||
(*ppInfo)->m_DataSize = DataSize;
|
||||
(*ppInfo)->m_Expiry = time_get() + time_freq() * NET_TOKENCACHE_PACKETEXPIRY;
|
||||
int64 Now = time_get();
|
||||
(*ppInfo)->m_Expiry = Now + time_freq() * NET_TOKENCACHE_PACKETEXPIRY;
|
||||
(*ppInfo)->m_LastTokenRequest = Now;
|
||||
(*ppInfo)->m_pNext = 0;
|
||||
if(pCallbackData)
|
||||
{
|
||||
(*ppInfo)->m_pfnCallback = pCallbackData->m_pfnCallback;
|
||||
(*ppInfo)->m_pCallbackUser = pCallbackData->m_pCallbackUser;
|
||||
pCallbackData->m_TrackID = (*ppInfo)->m_TrackID;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*ppInfo)->m_pfnCallback = 0;
|
||||
(*ppInfo)->m_pCallbackUser = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CNetTokenCache::PurgeStoredPacket(int TrackID)
|
||||
{
|
||||
CConnlessPacketInfo *pPrevInfo = 0;
|
||||
CConnlessPacketInfo *pInfo = m_pConnlessPacketList;
|
||||
while(pInfo)
|
||||
{
|
||||
if(pInfo->m_TrackID == TrackID)
|
||||
{
|
||||
// purge desired packet
|
||||
CConnlessPacketInfo *pNext = pInfo->m_pNext;
|
||||
if(pPrevInfo)
|
||||
pPrevInfo->m_pNext = pNext;
|
||||
if(pInfo == m_pConnlessPacketList)
|
||||
m_pConnlessPacketList = pNext;
|
||||
delete pInfo;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pPrevInfo)
|
||||
pPrevInfo = pPrevInfo->m_pNext;
|
||||
else
|
||||
pPrevInfo = pInfo;
|
||||
pInfo = pInfo->m_pNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,33 +255,30 @@ TOKEN CNetTokenCache::GetToken(const NETADDR *pAddr)
|
|||
void CNetTokenCache::FetchToken(const NETADDR *pAddr)
|
||||
{
|
||||
CNetBase::SendControlMsgWithToken(m_Socket, pAddr, NET_TOKEN_NONE, 0,
|
||||
NET_CTRLMSG_TOKEN, m_pTokenManager->GenerateToken(pAddr));
|
||||
NET_CTRLMSG_TOKEN, m_pTokenManager->GenerateToken(pAddr), true);
|
||||
}
|
||||
|
||||
void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token)
|
||||
void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token, int TokenFLag)
|
||||
{
|
||||
if(Token == NET_TOKEN_NONE)
|
||||
return;
|
||||
|
||||
CAddressInfo Info;
|
||||
Info.m_Addr = *pAddr;
|
||||
Info.m_Token = Token;
|
||||
Info.m_Expiry = time_get() + time_freq() * NET_TOKENCACHE_ADDRESSEXPIRY;
|
||||
|
||||
(*m_TokenCache.Allocate(sizeof(Info))) = Info;
|
||||
|
||||
// search the list of packets to be sent
|
||||
// for this address
|
||||
CConnlessPacketInfo *pPrevInfo = 0;
|
||||
CConnlessPacketInfo *pInfo = m_pConnlessPacketList;
|
||||
bool Found = false;
|
||||
while(pInfo)
|
||||
{
|
||||
static NETADDR NullAddr = { 0 };
|
||||
NullAddr.type = 7; // cover broadcasts
|
||||
NullAddr.port = pAddr->port;
|
||||
if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0 || net_addr_comp(&pInfo->m_Addr, &NullAddr) == 0)
|
||||
if(net_addr_comp(&pInfo->m_Addr, pAddr) == 0 || ((TokenFLag&NET_TOKENFLAG_ALLOWBROADCAST) && net_addr_comp(&pInfo->m_Addr, &NullAddr) == 0))
|
||||
{
|
||||
CNetBase::SendPacketConnless(m_Socket, pAddr, Token,
|
||||
// notify the user that the packet gets delivered
|
||||
if(pInfo->m_pfnCallback)
|
||||
pInfo->m_pfnCallback(pInfo->m_TrackID, pInfo->m_pCallbackUser);
|
||||
CNetBase::SendPacketConnless(m_Socket, &(pInfo->m_Addr), Token,
|
||||
m_pTokenManager->GenerateToken(pAddr),
|
||||
pInfo->m_aData, pInfo->m_DataSize);
|
||||
CConnlessPacketInfo *pNext = pInfo->m_pNext;
|
||||
|
@ -255,6 +298,16 @@ void CNetTokenCache::AddToken(const NETADDR *pAddr, TOKEN Token)
|
|||
pInfo = pInfo->m_pNext;
|
||||
}
|
||||
}
|
||||
|
||||
// add the token
|
||||
if(Found || !(TokenFLag&NET_TOKENFLAG_RESPONSEONLY))
|
||||
{
|
||||
CAddressInfo Info;
|
||||
Info.m_Addr = *pAddr;
|
||||
Info.m_Token = Token;
|
||||
Info.m_Expiry = time_get() + time_freq() * NET_TOKENCACHE_ADDRESSEXPIRY;
|
||||
(*m_TokenCache.Allocate(sizeof(Info))) = Info;
|
||||
}
|
||||
}
|
||||
|
||||
void CNetTokenCache::Update()
|
||||
|
@ -266,6 +319,17 @@ void CNetTokenCache::Update()
|
|||
while((pAddrInfo = m_TokenCache.First()) && (pAddrInfo->m_Expiry <= Now))
|
||||
m_TokenCache.PopFirst();
|
||||
|
||||
// try to fetch the token again for stored packets
|
||||
CConnlessPacketInfo * pEntry = m_pConnlessPacketList;
|
||||
while(pEntry)
|
||||
{
|
||||
if(pEntry->m_LastTokenRequest + 2*time_freq() <= Now)
|
||||
{
|
||||
FetchToken(&pEntry->m_Addr);
|
||||
pEntry->m_LastTokenRequest = Now;
|
||||
}
|
||||
pEntry = pEntry->m_pNext;
|
||||
}
|
||||
|
||||
// drop expired packets
|
||||
while(m_pConnlessPacketList && m_pConnlessPacketList->m_Expiry <= Now)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#ifndef ENGINE_TEXTRENDER_H
|
||||
#define ENGINE_TEXTRENDER_H
|
||||
#include "kernel.h"
|
||||
#include <base/vmath.h>
|
||||
#include <engine/graphics.h>
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -40,6 +42,11 @@ public:
|
|||
|
||||
//
|
||||
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) = 0;
|
||||
virtual void TextDeferredRenderEx(CTextCursor *pCursor, const char *pText, int Length,
|
||||
struct CQuadChar* aQuadChar, int QuadCharMaxCount, int* out_pQuadCharCount,
|
||||
IGraphics::CTextureHandle* pFontTexture) = 0;
|
||||
virtual void TextShadowed(CTextCursor *pCursor, const char *pText, int Length, vec2 ShadowOffset,
|
||||
vec4 ShadowColor, vec4 TextColor_) = 0;
|
||||
|
||||
// old foolish interface
|
||||
virtual void TextColor(float r, float g, float b, float a) = 0;
|
||||
|
@ -47,6 +54,8 @@ public:
|
|||
virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, int MaxWidth) = 0;
|
||||
virtual float TextWidth(void *pFontSetV, float Size, const char *pText, int Length) = 0;
|
||||
virtual int TextLineCount(void *pFontSetV, float Size, const char *pText, float LineWidth) = 0;
|
||||
|
||||
virtual float TextGetLineBaseY(const CTextCursor *pCursor) = 0;
|
||||
};
|
||||
|
||||
class IEngineTextRender : public ITextRender
|
||||
|
|
|
@ -14,14 +14,24 @@ CCamera::CCamera()
|
|||
{
|
||||
m_CamType = CAMTYPE_UNDEFINED;
|
||||
m_RotationCenter = vec2(0.0f, 0.0f);
|
||||
m_AnimationStartPos = vec2(0.0f, 0.0f);
|
||||
m_Center = vec2(0.0f, 0.0f);
|
||||
m_PrevCenter = vec2(0.0f, 0.0f);
|
||||
m_MenuCenter = vec2(0.0f, 0.0f);
|
||||
|
||||
m_Positions[POS_START] = vec2(500.0f, 500.0f);
|
||||
m_Positions[POS_INTERNET] = vec2(1000.0f, 1000.0f);
|
||||
m_Positions[POS_DEMOS] = vec2(500.0f, 1000.0f);
|
||||
m_Positions[POS_SETTINGS] = vec2(1000.0f, 500.0f);
|
||||
m_Positions[POS_LAN] = vec2(1100.0f, 1000.0f);
|
||||
m_Positions[POS_DEMOS] = vec2(1500.0f, 500.0f);
|
||||
m_Positions[POS_SETTINGS_GENERAL] = vec2(500.0f, 1000.0f);
|
||||
m_Positions[POS_SETTINGS_PLAYER] = vec2(600.0f, 1000.0f);
|
||||
m_Positions[POS_SETTINGS_TEE] = vec2(700.0f, 1000.0f);
|
||||
m_Positions[POS_SETTINGS_CONTROLS] = vec2(800.0f, 1000.0f);
|
||||
m_Positions[POS_SETTINGS_GRAPHICS] = vec2(900.0f, 1000.0f);
|
||||
m_Positions[POS_SETTINGS_SOUND] = vec2(1000.0f, 1000.0f);
|
||||
|
||||
m_CurrentPosition = -1;
|
||||
m_MoveTime = 0.0f;
|
||||
}
|
||||
|
||||
void CCamera::OnRender()
|
||||
|
@ -31,7 +41,8 @@ void CCamera::OnRender()
|
|||
m_Zoom = 1.0f;
|
||||
|
||||
// update camera center
|
||||
if(m_pClient->m_Snap.m_SpecInfo.m_Active && !m_pClient->m_Snap.m_SpecInfo.m_UsePosition)
|
||||
if(m_pClient->m_Snap.m_SpecInfo.m_Active && !m_pClient->m_Snap.m_SpecInfo.m_UsePosition &&
|
||||
(m_pClient->m_Snap.m_SpecInfo.m_SpecMode == SPEC_FREEVIEW || (m_pClient->m_Snap.m_pLocalInfo && !(m_pClient->m_Snap.m_pLocalInfo->m_PlayerFlags&PLAYERFLAG_DEAD))))
|
||||
{
|
||||
if(m_CamType != CAMTYPE_SPEC)
|
||||
{
|
||||
|
@ -52,7 +63,7 @@ void CCamera::OnRender()
|
|||
vec2 CameraOffset(0, 0);
|
||||
|
||||
float l = length(m_pClient->m_pControls->m_MousePos);
|
||||
if(l > 0.0001f) // make sure that this isn't 0
|
||||
if(g_Config.m_ClDynamicCamera && l > 0.0001f) // make sure that this isn't 0
|
||||
{
|
||||
float DeadZone = g_Config.m_ClMouseDeadzone;
|
||||
float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f;
|
||||
|
@ -81,9 +92,17 @@ void CCamera::OnRender()
|
|||
}
|
||||
else
|
||||
{
|
||||
Dir = normalize(m_RotationCenter-m_Center);
|
||||
m_Center += Dir*(500.0f*Client()->RenderFrameTime());
|
||||
Dir = normalize(m_Center-m_RotationCenter);
|
||||
// positions for the animation
|
||||
Dir = normalize(m_AnimationStartPos - m_RotationCenter);
|
||||
vec2 TargetPos = m_RotationCenter + Dir * (float)g_Config.m_ClRotationRadius;
|
||||
float Distance = distance(m_AnimationStartPos, TargetPos);
|
||||
|
||||
// move time
|
||||
m_MoveTime += Client()->RenderFrameTime()*g_Config.m_ClCameraSpeed / 10.0f;
|
||||
float XVal = 1 - m_MoveTime;
|
||||
XVal = pow(XVal, 7.0);
|
||||
|
||||
m_Center = TargetPos + Dir * (XVal*Distance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,8 +111,12 @@ void CCamera::OnRender()
|
|||
|
||||
void CCamera::ChangePosition(int PositionNumber)
|
||||
{
|
||||
if(PositionNumber < 0 || PositionNumber > NUM_POS-1)
|
||||
return;
|
||||
m_AnimationStartPos = m_Center;
|
||||
m_RotationCenter = m_Positions[PositionNumber];
|
||||
m_CurrentPosition = PositionNumber;
|
||||
m_MoveTime = 0.0f;
|
||||
}
|
||||
|
||||
int CCamera::GetCurrentPosition()
|
||||
|
|
|
@ -10,33 +10,34 @@ class CCamera : public CComponent
|
|||
public:
|
||||
enum
|
||||
{
|
||||
POS_START=0,
|
||||
POS_START = 0,
|
||||
POS_INTERNET,
|
||||
POS_LAN,
|
||||
POS_FAVORITES,
|
||||
POS_DEMOS,
|
||||
POS_SETTINGS,
|
||||
POS_SETTINGS_GENERAL, // order here should be the same like enum for settings pages in menu
|
||||
POS_SETTINGS_PLAYER,
|
||||
POS_SETTINGS_TEE,
|
||||
POS_SETTINGS_CONTROLS,
|
||||
POS_SETTINGS_GRAPHICS,
|
||||
POS_SETTINGS_SOUND,
|
||||
|
||||
NUM_POS,
|
||||
};
|
||||
|
||||
vec2 m_Center;
|
||||
vec2 m_MenuCenter;
|
||||
vec2 m_RotationCenter;
|
||||
float m_Zoom;
|
||||
|
||||
CCamera();
|
||||
virtual void OnRender();
|
||||
|
||||
void ChangePosition(int PositionNumber);
|
||||
int GetCurrentPosition();
|
||||
const vec2 *GetCenter() const { return &m_Center; };
|
||||
float GetZoom() const { return m_Zoom; };
|
||||
|
||||
static void ConSetPosition(IConsole::IResult *pResult, void *pUserData);
|
||||
|
||||
virtual void OnConsoleInit();
|
||||
virtual void OnStateChange(int NewState, int OldState);
|
||||
|
||||
public:
|
||||
private:
|
||||
enum
|
||||
{
|
||||
CAMTYPE_UNDEFINED=-1,
|
||||
|
@ -44,10 +45,16 @@ public:
|
|||
CAMTYPE_PLAYER,
|
||||
};
|
||||
|
||||
vec2 m_Center;
|
||||
vec2 m_MenuCenter;
|
||||
vec2 m_RotationCenter;
|
||||
float m_Zoom;
|
||||
int m_CamType;
|
||||
vec2 m_PrevCenter;
|
||||
vec2 m_Positions[NUM_POS];
|
||||
int m_CurrentPosition;
|
||||
vec2 m_AnimationStartPos;
|
||||
float m_MoveTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -81,7 +81,7 @@ void CChat::ConSayTeam(IConsole::IResult *pResult, void *pUserData)
|
|||
void CChat::ConWhisper(IConsole::IResult *pResult, void *pUserData)
|
||||
{
|
||||
CChat *pChat = (CChat *)pUserData;
|
||||
|
||||
|
||||
int Target = pResult->GetInteger(0);
|
||||
if(Target < 0 || Target >= MAX_CLIENTS || !pChat->m_pClient->m_aClients[Target].m_Active || pChat->m_pClient->m_LocalClientID == Target)
|
||||
pChat->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", "please enter a valid ClientID");
|
||||
|
@ -103,15 +103,15 @@ void CChat::ConChat(IConsole::IResult *pResult, void *pUserData)
|
|||
pChat->EnableMode(CHAT_TEAM);
|
||||
else if(str_comp(pMode, "whisper") == 0)
|
||||
{
|
||||
int Target = -1;
|
||||
int Target = pChat->m_WhisperTarget; // default to ID of last target
|
||||
if(pResult->NumArguments() == 2)
|
||||
Target = pResult->GetInteger(1);
|
||||
else
|
||||
{
|
||||
// pick next player as target
|
||||
// pick next valid player as target
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
int ClientID = (pChat->m_pClient->m_LocalClientID + i) % MAX_CLIENTS;
|
||||
int ClientID = (Target + i) % MAX_CLIENTS;
|
||||
if(pChat->m_pClient->m_aClients[ClientID].m_Active && pChat->m_pClient->m_LocalClientID != ClientID)
|
||||
{
|
||||
Target = ClientID;
|
||||
|
@ -161,7 +161,7 @@ bool CChat::OnInput(IInput::CEvent Event)
|
|||
{
|
||||
bool AddEntry = false;
|
||||
|
||||
if(m_LastChatSend+time_freq() < time_get())
|
||||
if(m_PendingChatCounter == 0 && m_LastChatSend+time_freq() < time_get())
|
||||
{
|
||||
Say(m_Mode, m_Input.GetString());
|
||||
AddEntry = true;
|
||||
|
@ -187,10 +187,14 @@ bool CChat::OnInput(IInput::CEvent Event)
|
|||
{
|
||||
if (m_Mode == CHAT_WHISPER)
|
||||
{
|
||||
// pick next player as target
|
||||
// change target
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
int ClientID = (m_WhisperTarget + i) % MAX_CLIENTS;
|
||||
int ClientID;
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))
|
||||
ClientID = (m_WhisperTarget + MAX_CLIENTS - i) % MAX_CLIENTS; // pick previous player as target
|
||||
else
|
||||
ClientID = (m_WhisperTarget + i) % MAX_CLIENTS; // pick next player as target
|
||||
if (m_pClient->m_aClients[ClientID].m_Active && m_WhisperTarget != ClientID && m_pClient->m_LocalClientID != ClientID)
|
||||
{
|
||||
m_WhisperTarget = ClientID;
|
||||
|
@ -299,7 +303,7 @@ bool CChat::OnInput(IInput::CEvent Event)
|
|||
if(m_Input.ProcessInput(Event))
|
||||
{
|
||||
m_InputUpdate = true;
|
||||
|
||||
|
||||
// reset name completion process
|
||||
m_CompletionChosen = -1;
|
||||
}
|
||||
|
@ -359,11 +363,11 @@ void CChat::OnMessage(int MsgType, void *pRawMsg)
|
|||
if(MsgType == NETMSGTYPE_SV_CHAT)
|
||||
{
|
||||
CNetMsg_Sv_Chat *pMsg = (CNetMsg_Sv_Chat *)pRawMsg;
|
||||
AddLine(pMsg->m_ClientID, pMsg->m_Mode, pMsg->m_pMessage);
|
||||
AddLine(pMsg->m_ClientID, pMsg->m_Mode, pMsg->m_pMessage, pMsg->m_TargetID);
|
||||
}
|
||||
}
|
||||
|
||||
void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
||||
void CChat::AddLine(int ClientID, int Mode, const char *pLine, int TargetID)
|
||||
{
|
||||
if(*pLine == 0 || (ClientID != -1 && (!g_Config.m_ClShowsocial || m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client
|
||||
m_pClient->m_aClients[ClientID].m_ChatIgnore ||
|
||||
|
@ -376,7 +380,7 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
|||
const char *pStr = pLine;
|
||||
const char *pEnd = 0;
|
||||
while(*pStr)
|
||||
{
|
||||
{
|
||||
const char *pStrOld = pStr;
|
||||
int Code = str_utf8_decode(&pStr);
|
||||
|
||||
|
@ -395,7 +399,7 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
|||
*(const_cast<char *>(pStr)) = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pEnd != 0)
|
||||
*(const_cast<char *>(pEnd)) = 0;
|
||||
|
||||
|
@ -416,15 +420,17 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
|||
|
||||
m_CurrentLine = (m_CurrentLine+1)%MAX_LINES;
|
||||
m_aLines[m_CurrentLine].m_Time = time_get();
|
||||
m_aLines[m_CurrentLine].m_YOffset[0] = -1.0f;
|
||||
m_aLines[m_CurrentLine].m_YOffset[1] = -1.0f;
|
||||
m_aLines[m_CurrentLine].m_Size[0].y = -1.0f;
|
||||
m_aLines[m_CurrentLine].m_Size[1].y = -1.0f;
|
||||
m_aLines[m_CurrentLine].m_ClientID = ClientID;
|
||||
m_aLines[m_CurrentLine].m_TargetID = TargetID;
|
||||
m_aLines[m_CurrentLine].m_Mode = Mode;
|
||||
m_aLines[m_CurrentLine].m_NameColor = -2;
|
||||
|
||||
// check for highlighted name
|
||||
Highlighted = false;
|
||||
if(ClientID != m_pClient->m_LocalClientID) // do not highlight our own messages
|
||||
// do not highlight our own messages, whispers and system messages
|
||||
if(Mode != CHAT_WHISPER && ClientID != -1 && ClientID != m_pClient->m_LocalClientID)
|
||||
{
|
||||
const char *pHL = str_find_nocase(pLine, m_pClient->m_aClients[m_pClient->m_LocalClientID].m_aName);
|
||||
if(pHL)
|
||||
|
@ -441,12 +447,16 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
|||
}
|
||||
}
|
||||
|
||||
m_aLines[m_CurrentLine].m_Highlighted = Highlighted || Mode == CHAT_WHISPER;
|
||||
m_aLines[m_CurrentLine].m_Highlighted = Highlighted;
|
||||
|
||||
int NameCID = ClientID;
|
||||
if(Mode == CHAT_WHISPER && ClientID == m_pClient->m_LocalClientID && TargetID >= 0)
|
||||
NameCID = TargetID;
|
||||
|
||||
if(ClientID == -1) // server message
|
||||
{
|
||||
str_copy(m_aLines[m_CurrentLine].m_aName, "*** ", sizeof(m_aLines[m_CurrentLine].m_aName));
|
||||
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine);
|
||||
m_aLines[m_CurrentLine].m_aName[0] = 0;
|
||||
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "*** %s", pLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -461,8 +471,8 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
|||
m_aLines[m_CurrentLine].m_NameColor = TEAM_BLUE;
|
||||
}
|
||||
|
||||
str_format(m_aLines[m_CurrentLine].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName), "%2d: %s", ClientID, m_pClient->m_aClients[ClientID].m_aName);
|
||||
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), ": %s", pLine);
|
||||
str_format(m_aLines[m_CurrentLine].m_aName, sizeof(m_aLines[m_CurrentLine].m_aName), "%s", m_pClient->m_aClients[NameCID].m_aName);
|
||||
str_format(m_aLines[m_CurrentLine].m_aText, sizeof(m_aLines[m_CurrentLine].m_aText), "%s", pLine);
|
||||
}
|
||||
|
||||
char aBuf[1024];
|
||||
|
@ -473,8 +483,9 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
|||
str_copy(aBufMode, "teamchat", sizeof(aBufMode));
|
||||
else
|
||||
str_copy(aBufMode, "chat", sizeof(aBufMode));
|
||||
str_format(aBuf, sizeof(aBuf), "%s%s", m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, aBufMode, aBuf, Highlighted);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%2d: %s: %s", NameCID, m_aLines[m_CurrentLine].m_aName, m_aLines[m_CurrentLine].m_aText);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, aBufMode, aBuf, Highlighted || Mode == CHAT_WHISPER);
|
||||
}
|
||||
|
||||
// play sound
|
||||
|
@ -487,7 +498,7 @@ void CChat::AddLine(int ClientID, int Mode, const char *pLine)
|
|||
m_aLastSoundPlayed[CHAT_SERVER] = Now;
|
||||
}
|
||||
}
|
||||
else if(Highlighted)
|
||||
else if(Highlighted || Mode == CHAT_WHISPER)
|
||||
{
|
||||
if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10)
|
||||
{
|
||||
|
@ -528,28 +539,107 @@ void CChat::OnRender()
|
|||
|
||||
float Width = 300.0f*Graphics()->ScreenAspect();
|
||||
Graphics()->MapScreen(0.0f, 0.0f, Width, 300.0f);
|
||||
float x = 5.0f;
|
||||
float x = 12.0f;
|
||||
float y = 300.0f-20.0f;
|
||||
const int LocalCID = m_pClient->m_LocalClientID;
|
||||
const CGameClient::CClientData& LocalClient = m_pClient->m_aClients[LocalCID];
|
||||
const int LocalTteam = LocalClient.m_Team;
|
||||
|
||||
if(m_Mode != CHAT_NONE)
|
||||
{
|
||||
// calculate category text size
|
||||
// TODO: rework TextRender. Writing the same code twice to calculate a simple thing as width is ridiculus
|
||||
float CategoryWidth = 0;
|
||||
float CategoryHeight;
|
||||
const float CategoryFontSize = 8.0f;
|
||||
const float InputFontSize = 8.0f;
|
||||
char aCatText[48];
|
||||
|
||||
{
|
||||
CTextCursor Cursor;
|
||||
TextRender()->SetCursor(&Cursor, x, y, CategoryFontSize, 0);
|
||||
|
||||
if(m_Mode == CHAT_ALL)
|
||||
str_copy(aCatText, Localize("All"), sizeof(aCatText));
|
||||
else if(m_Mode == CHAT_TEAM)
|
||||
{
|
||||
if(LocalTteam == TEAM_SPECTATORS)
|
||||
str_copy(aCatText, Localize("Spectators"), sizeof(aCatText));
|
||||
else
|
||||
str_copy(aCatText, Localize("Team"), sizeof(aCatText));
|
||||
}
|
||||
else if(m_Mode == CHAT_WHISPER)
|
||||
{
|
||||
CategoryWidth += RenderTools()->GetClientIdRectSize(CategoryFontSize);
|
||||
str_format(aCatText, sizeof(aCatText), "%s",m_pClient->m_aClients[m_WhisperTarget].m_aName);
|
||||
}
|
||||
else
|
||||
str_copy(aCatText, Localize("Chat"), sizeof(aCatText));
|
||||
|
||||
TextRender()->TextEx(&Cursor, aCatText, -1);
|
||||
|
||||
CategoryWidth += Cursor.m_X - Cursor.m_StartX;
|
||||
CategoryHeight = Cursor.m_FontSize;
|
||||
}
|
||||
|
||||
// draw a background box
|
||||
const vec4 CRCWhite(1, 1, 1, 0.25);
|
||||
const vec4 CRCTeam(0.4, 1, 0.4, 0.4);
|
||||
const vec4 CRCWhisper(0, 0.5, 1, 0.5);
|
||||
|
||||
vec4 CatRectColor = CRCWhite;
|
||||
if(m_Mode == CHAT_TEAM)
|
||||
CatRectColor = CRCTeam;
|
||||
else if(m_Mode == CHAT_WHISPER)
|
||||
CatRectColor = CRCWhisper;
|
||||
|
||||
const float IconOffsetX = m_Mode == CHAT_WHISPER ? 6.0f : 0.0f;
|
||||
|
||||
CUIRect CatRect;
|
||||
CatRect.x = 0;
|
||||
CatRect.y = y;
|
||||
CatRect.w = CategoryWidth + x + 2.0f + IconOffsetX;
|
||||
CatRect.h = CategoryHeight + 4.0f;
|
||||
RenderTools()->DrawUIRect(&CatRect, CatRectColor, CUI::CORNER_R, 2.0f);
|
||||
|
||||
// draw chat icon
|
||||
Graphics()->WrapClamp();
|
||||
IGraphics::CQuadItem QuadIcon;
|
||||
|
||||
if(m_Mode == CHAT_WHISPER)
|
||||
{
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CHATWHISPER].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->QuadsSetSubset(1, 0, 0, 1);
|
||||
QuadIcon = IGraphics::CQuadItem(1.5f, y + (CatRect.h - 8.0f) * 0.5f, 16.f, 8.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
RenderTools()->SelectSprite(SPRITE_DOTDOT);
|
||||
QuadIcon = IGraphics::CQuadItem(1.0f, y, 10.f, 10.0f);
|
||||
}
|
||||
|
||||
Graphics()->SetColor(1, 1, 1, 1);
|
||||
Graphics()->QuadsDrawTL(&QuadIcon, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
Graphics()->WrapNormal();
|
||||
|
||||
// render chat input
|
||||
CTextCursor Cursor;
|
||||
TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER);
|
||||
TextRender()->SetCursor(&Cursor, x + IconOffsetX, y, CategoryFontSize, TEXTFLAG_RENDER);
|
||||
Cursor.m_LineWidth = Width-190.0f;
|
||||
Cursor.m_MaxLines = 2;
|
||||
|
||||
char aBuf[32];
|
||||
if(m_Mode == CHAT_ALL)
|
||||
str_copy(aBuf, Localize("All"), sizeof(aBuf));
|
||||
else if(m_Mode == CHAT_TEAM)
|
||||
str_copy(aBuf, Localize("Team"), sizeof(aBuf));
|
||||
else if(m_Mode == CHAT_WHISPER)
|
||||
str_format(aBuf, sizeof(aBuf), "%s %2d: %s", Localize("To"), m_WhisperTarget, m_pClient->m_aClients[m_WhisperTarget].m_aName);
|
||||
else
|
||||
str_copy(aBuf, Localize("Chat"), sizeof(aBuf));
|
||||
|
||||
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||
TextRender()->TextEx(&Cursor, ": ", -1);
|
||||
if(m_Mode == CHAT_WHISPER)
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, m_WhisperTarget);
|
||||
TextRender()->TextEx(&Cursor, aCatText, -1);
|
||||
|
||||
Cursor.m_X += 4.0f;
|
||||
Cursor.m_Y -= (InputFontSize-CategoryFontSize) * 0.5f;
|
||||
Cursor.m_StartX = Cursor.m_X;
|
||||
Cursor.m_FontSize = InputFontSize;
|
||||
|
||||
// check if the visible text has to be moved
|
||||
if(m_InputUpdate)
|
||||
|
@ -587,70 +677,242 @@ void CChat::OnRender()
|
|||
|
||||
y -= 8.0f;
|
||||
|
||||
// show all chat when typing
|
||||
m_Show |= m_Mode != CHAT_NONE;
|
||||
|
||||
int64 Now = time_get();
|
||||
const int64 TimeFreq = time_freq();
|
||||
float LineWidth = m_pClient->m_pScoreboard->Active() ? 90.0f : 200.0f;
|
||||
float HeightLimit = m_pClient->m_pScoreboard->Active() ? 230.0f : m_Show ? 50.0f : 200.0f;
|
||||
float HeightLimit = m_pClient->m_pScoreboard->Active() ? 230.0f : m_Show ? 90.0f : 200.0f;
|
||||
float Begin = x;
|
||||
float FontSize = 6.0f;
|
||||
CTextCursor Cursor;
|
||||
int OffsetType = m_pClient->m_pScoreboard->Active() ? 1 : 0;
|
||||
|
||||
// get the y offset (calculate it if we haven't done that yet)
|
||||
for(int i = 0; i < MAX_LINES; i++)
|
||||
{
|
||||
int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES;
|
||||
if(Now > m_aLines[r].m_Time+16*time_freq() && !m_Show)
|
||||
break;
|
||||
CLine& Line = m_aLines[r];
|
||||
|
||||
// get the y offset (calculate it if we haven't done that yet)
|
||||
if(m_aLines[r].m_YOffset[OffsetType] < 0.0f)
|
||||
if(m_aLines[r].m_aText[0] == 0) break;
|
||||
|
||||
if(Line.m_Size[OffsetType].y < 0.0f)
|
||||
{
|
||||
TextRender()->SetCursor(&Cursor, Begin, 0.0f, FontSize, 0);
|
||||
Cursor.m_LineWidth = LineWidth;
|
||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1);
|
||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1);
|
||||
m_aLines[r].m_YOffset[OffsetType] = Cursor.m_Y + Cursor.m_FontSize;
|
||||
|
||||
char aBuf[768] = {0};
|
||||
if(Line.m_Mode == CHAT_TEAM)
|
||||
str_format(aBuf, sizeof(aBuf), "[%s] ", Localize("Team"));
|
||||
else if(Line.m_Mode == CHAT_WHISPER)
|
||||
str_format(aBuf, sizeof(aBuf), "[%s] ", Localize("Whisper"));
|
||||
|
||||
if(Line.m_ClientID != -1)
|
||||
{
|
||||
Cursor.m_X += RenderTools()->GetClientIdRectSize(Cursor.m_FontSize);
|
||||
str_append(aBuf, Line.m_aName, sizeof(aBuf));
|
||||
str_append(aBuf, ": ", sizeof(aBuf));
|
||||
}
|
||||
|
||||
str_append(aBuf, Line.m_aText, sizeof(aBuf));
|
||||
|
||||
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||
// FIXME: sometimes an empty line will pop here when the cursor reaches the end of line
|
||||
Line.m_Size[OffsetType].y = Cursor.m_LineCount * Cursor.m_FontSize;
|
||||
Line.m_Size[OffsetType].x = Cursor.m_LineCount == 1 ? Cursor.m_X - Cursor.m_StartX : LineWidth;
|
||||
}
|
||||
y -= m_aLines[r].m_YOffset[OffsetType];
|
||||
}
|
||||
|
||||
if(m_Show)
|
||||
{
|
||||
CUIRect Rect;
|
||||
Rect.x = 0;
|
||||
Rect.y = HeightLimit - 2.0f;
|
||||
Rect.w = LineWidth + x;
|
||||
Rect.h = 300 - HeightLimit - 22.f;
|
||||
|
||||
const float LeftAlpha = 0.85f;
|
||||
const float RightAlpha = 0.05f;
|
||||
RenderTools()->DrawUIRect4(&Rect,
|
||||
vec4(0, 0, 0, LeftAlpha),
|
||||
vec4(0, 0, 0, RightAlpha),
|
||||
vec4(0, 0, 0, LeftAlpha),
|
||||
vec4(0, 0, 0, RightAlpha),
|
||||
CUI::CORNER_R, 3.0f);
|
||||
}
|
||||
|
||||
for(int i = 0; i < MAX_LINES; i++)
|
||||
{
|
||||
int r = ((m_CurrentLine-i)+MAX_LINES)%MAX_LINES;
|
||||
CLine& Line = m_aLines[r];
|
||||
|
||||
if(m_aLines[r].m_aText[0] == 0) break;
|
||||
|
||||
if(Now > Line.m_Time+16*TimeFreq && !m_Show)
|
||||
break;
|
||||
|
||||
y -= Line.m_Size[OffsetType].y;
|
||||
|
||||
// cut off if msgs waste too much space
|
||||
if(y < HeightLimit)
|
||||
break;
|
||||
|
||||
float Blend = Now > m_aLines[r].m_Time+14*time_freq() && !m_Show ? 1.0f-(Now-m_aLines[r].m_Time-14*time_freq())/(2.0f*time_freq()) : 1.0f;
|
||||
float Blend = Now > Line.m_Time+14*TimeFreq && !m_Show ? 1.0f-(Now-Line.m_Time-14*TimeFreq)/(2.0f*TimeFreq) : 1.0f;
|
||||
|
||||
const float HlTimeFull = 1.0f;
|
||||
const float HlTimeFade = 1.0f;
|
||||
|
||||
float Delta = (Now - Line.m_Time) / (float)TimeFreq;
|
||||
const float HighlightBlend = 1.0f - clamp(Delta - HlTimeFull, 0.0f, HlTimeFade) / HlTimeFade;
|
||||
|
||||
// reset the cursor
|
||||
TextRender()->SetCursor(&Cursor, Begin, y, FontSize, TEXTFLAG_RENDER);
|
||||
Cursor.m_LineWidth = LineWidth;
|
||||
|
||||
// render name
|
||||
if(m_aLines[r].m_ClientID == -1)
|
||||
TextRender()->TextColor(1.0f, 1.0f, 0.5f, Blend); // system
|
||||
else if(m_aLines[r].m_Mode == CHAT_TEAM)
|
||||
TextRender()->TextColor(0.45f, 0.9f, 0.45f, Blend); // team message
|
||||
else if(m_aLines[r].m_NameColor == TEAM_RED)
|
||||
TextRender()->TextColor(1.0f, 0.5f, 0.5f, Blend); // red
|
||||
else if(m_aLines[r].m_NameColor == TEAM_BLUE)
|
||||
TextRender()->TextColor(0.7f, 0.7f, 1.0f, Blend); // blue
|
||||
else if(m_aLines[r].m_NameColor == TEAM_SPECTATORS)
|
||||
TextRender()->TextColor(0.75f, 0.5f, 0.75f, Blend); // spectator
|
||||
else
|
||||
TextRender()->TextColor(0.8f, 0.8f, 0.8f, Blend);
|
||||
const vec2 ShadowOffset(0.8f, 1.5f);
|
||||
const vec4 ShadowWhisper(0.09f, 0.f, 0.26f, Blend * 0.9f);
|
||||
const vec4 ShadowBlack(0, 0, 0, Blend * 0.9f);
|
||||
vec4 ShadowColor = ShadowBlack;
|
||||
|
||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1);
|
||||
if(Line.m_Mode == CHAT_WHISPER)
|
||||
ShadowColor = ShadowWhisper;
|
||||
|
||||
|
||||
const vec4 ColorSystem(1.0f, 1.0f, 0.5f, Blend);
|
||||
const vec4 ColorWhisper(0.4f, 1.0f, 1.0f, Blend);
|
||||
const vec4 ColorRed(1.0f, 0.5f, 0.5f, Blend);
|
||||
const vec4 ColorBlue(0.7f, 0.7f, 1.0f, Blend);
|
||||
const vec4 ColorSpec(0.75f, 0.5f, 0.75f, Blend);
|
||||
const vec4 ColorAllPre(0.8f, 0.8f, 0.8f, Blend);
|
||||
const vec4 ColorAllText(1.0f, 1.0f, 1.0f, Blend);
|
||||
const vec4 ColorTeamPre(0.45f, 0.9f, 0.45f, Blend);
|
||||
const vec4 ColorTeamText(0.6f, 1.0f, 0.6f, Blend);
|
||||
const vec4 ColorHighlightBg(0.0f, 0.27f, 0.9f, 0.5f * HighlightBlend);
|
||||
const vec4 ColorHighlightOutline(0.0f, 0.4f, 1.0f,
|
||||
mix(Line.m_Mode == CHAT_TEAM ? 0.6f : 0.5f, 1.0f, HighlightBlend));
|
||||
|
||||
vec4 TextColor = ColorAllText;
|
||||
|
||||
if(Line.m_Highlighted && ColorHighlightBg.a > 0.001f)
|
||||
{
|
||||
CUIRect BgRect;
|
||||
BgRect.x = Cursor.m_X;
|
||||
BgRect.y = Cursor.m_Y + 2.0f;
|
||||
BgRect.w = Line.m_Size[OffsetType].x - 2.0f;
|
||||
BgRect.h = Line.m_Size[OffsetType].y;
|
||||
|
||||
vec4 LeftColor = ColorHighlightBg * ColorHighlightBg.a;
|
||||
LeftColor.a = ColorHighlightBg.a;
|
||||
|
||||
vec4 RightColor = ColorHighlightBg;
|
||||
RightColor *= 0.1f;
|
||||
|
||||
RenderTools()->DrawUIRect4(&BgRect,
|
||||
LeftColor,
|
||||
RightColor,
|
||||
LeftColor,
|
||||
RightColor,
|
||||
CUI::CORNER_R, 2.0f);
|
||||
}
|
||||
|
||||
char aBuf[48];
|
||||
if(Line.m_Mode == CHAT_WHISPER)
|
||||
{
|
||||
const float LineBaseY = TextRender()->TextGetLineBaseY(&Cursor);
|
||||
|
||||
const float qw = 10.0f;
|
||||
const float qh = 5.0f;
|
||||
const float qx = Cursor.m_X + 2.0f;
|
||||
const float qy = LineBaseY - qh - 0.5f;
|
||||
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CHATWHISPER].m_Id);
|
||||
Graphics()->WrapClamp();
|
||||
|
||||
Graphics()->QuadsBegin();
|
||||
|
||||
// image orientation
|
||||
const int LocalCID = m_pClient->m_LocalClientID;
|
||||
if(Line.m_ClientID == LocalCID && Line.m_TargetID >= 0)
|
||||
Graphics()->QuadsSetSubset(1, 0, 0, 1); // To
|
||||
else if(Line.m_TargetID == LocalCID)
|
||||
Graphics()->QuadsSetSubset(0, 0, 1, 1); // From
|
||||
else
|
||||
dbg_break();
|
||||
|
||||
|
||||
// shadow pass
|
||||
Graphics()->SetColor(ShadowWhisper.r*ShadowWhisper.a*Blend, ShadowWhisper.g*ShadowWhisper.a*Blend,
|
||||
ShadowWhisper.b*ShadowWhisper.a*Blend, ShadowWhisper.a*Blend);
|
||||
IGraphics::CQuadItem Quad(qx + 0.2f, qy + 0.5f, qw, qh);
|
||||
Graphics()->QuadsDrawTL(&Quad, 1);
|
||||
|
||||
// color pass
|
||||
Graphics()->SetColor(ColorWhisper.r*Blend, ColorWhisper.g*Blend, ColorWhisper.b*Blend, Blend);
|
||||
Quad = IGraphics::CQuadItem(qx, qy, qw, qh);
|
||||
Graphics()->QuadsDrawTL(&Quad, 1);
|
||||
|
||||
Graphics()->QuadsEnd();
|
||||
Graphics()->WrapNormal();
|
||||
Cursor.m_X += 12.5f;
|
||||
}
|
||||
|
||||
// render name
|
||||
if(Line.m_ClientID == -1)
|
||||
TextColor = ColorSystem;
|
||||
else if(Line.m_Mode == CHAT_WHISPER)
|
||||
TextColor = ColorWhisper;
|
||||
else if(Line.m_Mode == CHAT_TEAM)
|
||||
TextColor = ColorTeamPre;
|
||||
else if(Line.m_NameColor == TEAM_RED)
|
||||
TextColor = ColorRed;
|
||||
else if(Line.m_NameColor == TEAM_BLUE)
|
||||
TextColor = ColorBlue;
|
||||
else if(Line.m_NameColor == TEAM_SPECTATORS)
|
||||
TextColor = ColorSpec;
|
||||
else
|
||||
TextColor = ColorAllPre;
|
||||
|
||||
if(Line.m_ClientID != -1)
|
||||
{
|
||||
int NameCID = Line.m_ClientID;
|
||||
if(Line.m_Mode == CHAT_WHISPER && Line.m_ClientID == m_pClient->m_LocalClientID && Line.m_TargetID >= 0)
|
||||
NameCID = Line.m_TargetID;
|
||||
|
||||
vec4 BgIdColor = TextColor;
|
||||
BgIdColor.a = 0.5f;
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, NameCID, BgIdColor);
|
||||
str_format(aBuf, sizeof(aBuf), "%s: ", Line.m_aName);
|
||||
TextRender()->TextShadowed(&Cursor, aBuf, -1, ShadowOffset, ShadowColor, TextColor);
|
||||
}
|
||||
|
||||
// render line
|
||||
if(m_aLines[r].m_ClientID == -1)
|
||||
TextRender()->TextColor(1.0f, 1.0f, 0.5f, Blend); // system
|
||||
else if(m_aLines[r].m_Highlighted)
|
||||
TextRender()->TextColor(1.0f, 0.5f, 0.5f, Blend); // highlighted
|
||||
else if(m_aLines[r].m_Mode == CHAT_TEAM)
|
||||
TextRender()->TextColor(0.65f, 1.0f, 0.65f, Blend); // team message
|
||||
if(Line.m_ClientID == -1)
|
||||
TextColor = ColorSystem;
|
||||
else if(Line.m_Mode == CHAT_WHISPER)
|
||||
TextColor = ColorWhisper;
|
||||
else if(Line.m_Mode == CHAT_TEAM)
|
||||
TextColor = ColorTeamText;
|
||||
else
|
||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Blend);
|
||||
TextColor = ColorAllText;
|
||||
|
||||
TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1);
|
||||
if(Line.m_Highlighted)
|
||||
{
|
||||
TextRender()->TextColor(TextColor.r, TextColor.g, TextColor.b, TextColor.a);
|
||||
|
||||
TextRender()->TextOutlineColor(ColorHighlightOutline.r,
|
||||
ColorHighlightOutline.g,
|
||||
ColorHighlightOutline.b,
|
||||
ColorHighlightOutline.a);
|
||||
|
||||
TextRender()->TextEx(&Cursor, Line.m_aText, -1);
|
||||
}
|
||||
else
|
||||
TextRender()->TextShadowed(&Cursor, Line.m_aText, -1, ShadowOffset, ShadowColor, TextColor);
|
||||
}
|
||||
|
||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
}
|
||||
|
||||
void CChat::Say(int Mode, const char *pLine)
|
||||
|
|
|
@ -12,14 +12,15 @@ class CChat : public CComponent
|
|||
|
||||
enum
|
||||
{
|
||||
MAX_LINES = 25,
|
||||
MAX_LINES = 50,
|
||||
};
|
||||
|
||||
struct CLine
|
||||
{
|
||||
int64 m_Time;
|
||||
float m_YOffset[2];
|
||||
vec2 m_Size[2];
|
||||
int m_ClientID;
|
||||
int m_TargetID;
|
||||
int m_Mode;
|
||||
int m_NameColor;
|
||||
char m_aName[64];
|
||||
|
@ -74,7 +75,7 @@ public:
|
|||
|
||||
bool IsActive() const { return m_Mode != CHAT_NONE; }
|
||||
|
||||
void AddLine(int ClientID, int Team, const char *pLine);
|
||||
void AddLine(int ClientID, int Team, const char *pLine, int TargetID = -1);
|
||||
|
||||
void EnableMode(int Team);
|
||||
|
||||
|
|
|
@ -227,9 +227,15 @@ void CControls::ClampMousePos()
|
|||
}
|
||||
else
|
||||
{
|
||||
float CameraMaxDistance = 200.0f;
|
||||
float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f;
|
||||
float MouseMax = min(CameraMaxDistance/FollowFactor + g_Config.m_ClMouseDeadzone, (float)g_Config.m_ClMouseMaxDistance);
|
||||
float MouseMax;
|
||||
if(g_Config.m_ClDynamicCamera)
|
||||
{
|
||||
float CameraMaxDistance = 200.0f;
|
||||
float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f;
|
||||
MouseMax = min(CameraMaxDistance/FollowFactor + g_Config.m_ClMouseDeadzone, (float)g_Config.m_ClMouseMaxDistanceDynamic);
|
||||
}
|
||||
else
|
||||
MouseMax = (float)g_Config.m_ClMouseMaxDistanceStatic;
|
||||
|
||||
if(length(m_MousePos) > MouseMax)
|
||||
m_MousePos = normalize(m_MousePos)*MouseMax;
|
||||
|
|
|
@ -24,20 +24,20 @@ void CCountryFlags::LoadCountryflagsIndexfile()
|
|||
return;
|
||||
}
|
||||
int FileSize = (int)io_length(File);
|
||||
char *pFileData = (char *)mem_alloc(FileSize+1, 1);
|
||||
char *pFileData = (char *)mem_alloc(FileSize, 1);
|
||||
io_read(File, pFileData, FileSize);
|
||||
pFileData[FileSize] = 0;
|
||||
io_close(File);
|
||||
|
||||
// parse json data
|
||||
json_settings JsonSettings;
|
||||
mem_zero(&JsonSettings, sizeof(JsonSettings));
|
||||
char aError[256];
|
||||
json_value *pJsonData = json_parse_ex(&JsonSettings, pFileData, aError);
|
||||
json_value *pJsonData = json_parse_ex(&JsonSettings, pFileData, FileSize, aError);
|
||||
mem_free(pFileData);
|
||||
|
||||
if(pJsonData == 0)
|
||||
{
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, pFilename, aError);
|
||||
mem_free(pFileData);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -60,14 +60,14 @@ void CCountryFlags::LoadCountryflagsIndexfile()
|
|||
char aBuf[64];
|
||||
|
||||
// validate country code
|
||||
int CountryCode = (long)rStart[i]["code"];
|
||||
int CountryCode = (json_int_t)rStart[i]["code"];
|
||||
if(CountryCode < CODE_LB || CountryCode > CODE_UB)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "country code '%i' not within valid code range [%i..%i]", CountryCode, CODE_LB, CODE_UB);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// add entry
|
||||
const char *pCountryName = rStart[i]["id"];
|
||||
CCountryFlag CountryFlag;
|
||||
|
@ -89,7 +89,7 @@ void CCountryFlags::LoadCountryflagsIndexfile()
|
|||
mem_free(Info.m_pData);
|
||||
}
|
||||
m_aCountryFlags.add_unsorted(CountryFlag);
|
||||
|
||||
|
||||
// print message
|
||||
if(g_Config.m_Debug)
|
||||
{
|
||||
|
@ -103,7 +103,6 @@ void CCountryFlags::LoadCountryflagsIndexfile()
|
|||
|
||||
// clean up
|
||||
json_value_free(pJsonData);
|
||||
mem_free(pFileData);
|
||||
m_aCountryFlags.sort_range();
|
||||
|
||||
// find index of default item
|
||||
|
@ -114,7 +113,7 @@ void CCountryFlags::LoadCountryflagsIndexfile()
|
|||
DefaultIndex = Index;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// init LUT
|
||||
if(DefaultIndex != 0)
|
||||
for(int i = 0; i < CODE_RANGE; ++i)
|
||||
|
@ -162,7 +161,7 @@ void CCountryFlags::Render(int CountryCode, const vec4 *pColor, float x, float y
|
|||
{
|
||||
Graphics()->TextureSet(pFlag->m_Texture);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(pColor->r, pColor->g, pColor->b, pColor->a);
|
||||
Graphics()->SetColor(pColor->r*pColor->a, pColor->g*pColor->a, pColor->b*pColor->a, pColor->a);
|
||||
IGraphics::CQuadItem QuadItem(x, y, w, h);
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
|
|
|
@ -70,7 +70,8 @@ void CDamageInd::OnRender()
|
|||
else
|
||||
{
|
||||
vec2 Pos = mix(m_aItems[i].m_Pos+m_aItems[i].m_Dir*75.0f, m_aItems[i].m_Pos, clamp((Life-0.60f)/0.15f, 0.0f, 1.0f));
|
||||
Graphics()->SetColor(1.0f,1.0f,1.0f, Life/0.1f);
|
||||
const float Alpha = clamp(Life * 10.0f, 0.0f, 1.0f); // 0.1 -> 0.0 == 1.0 -> 0.0
|
||||
Graphics()->SetColor(1.0f*Alpha, 1.0f*Alpha, 1.0f*Alpha, Alpha);
|
||||
Graphics()->QuadsSetRotation(m_aItems[i].m_StartAngle + Life * 2.0f);
|
||||
RenderTools()->SelectSprite(SPRITE_STAR1);
|
||||
RenderTools()->DrawSprite(Pos.x, Pos.y, 48.0f);
|
||||
|
|
|
@ -155,11 +155,13 @@ void CEmoticon::OnRender()
|
|||
Graphics()->QuadsEnd();
|
||||
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id);
|
||||
Graphics()->WrapClamp();
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1,1,1,1);
|
||||
IGraphics::CQuadItem QuadItem(m_SelectorMouse.x+Screen.w/2,m_SelectorMouse.y+Screen.h/2,24,24);
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
Graphics()->WrapNormal();
|
||||
}
|
||||
|
||||
void CEmoticon::Emote(int Emoticon)
|
||||
|
|
|
@ -22,7 +22,7 @@ CHud::CHud()
|
|||
{
|
||||
// won't work if zero
|
||||
m_AverageFPS = 1.0f;
|
||||
|
||||
|
||||
m_WarmupHideTick = 0;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ void CHud::RenderStartCountdown()
|
|||
|
||||
if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0)
|
||||
return;
|
||||
|
||||
|
||||
FontSize = 16.0f;
|
||||
char aBuf[32];
|
||||
int Seconds = (m_pClient->m_Snap.m_pGameData->m_GameStateEndTick-Client()->GameTick()+SERVER_TICK_SPEED-1)/SERVER_TICK_SPEED;
|
||||
|
@ -209,9 +209,16 @@ void CHud::RenderScoreHud()
|
|||
// draw name of the flag holder
|
||||
int ID = FlagCarrier[t]%MAX_CLIENTS;
|
||||
char aName[64];
|
||||
str_format(aName, sizeof(aName), "%2d: %s", ID, g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : "");
|
||||
float w = TextRender()->TextWidth(0, 8.0f, aName, -1);
|
||||
TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split), StartY+(t+1)*20.0f-3.0f, 8.0f, aName, -1);
|
||||
str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : "");
|
||||
float w = TextRender()->TextWidth(0, 8.0f, aName, -1) + RenderTools()->GetClientIdRectSize(8.0f);
|
||||
|
||||
CTextCursor Cursor;
|
||||
float x = min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split);
|
||||
float y = StartY+(t+1)*20.0f-3.0f;
|
||||
TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER);
|
||||
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, ID);
|
||||
TextRender()->TextEx(&Cursor, aName, -1);
|
||||
|
||||
// draw tee of the flag holder
|
||||
CTeeRenderInfo Info = m_pClient->m_aClients[ID].m_RenderInfo;
|
||||
|
@ -279,19 +286,26 @@ void CHud::RenderScoreHud()
|
|||
TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, StartY+t*20, 14.0f, aScore[t], -1);
|
||||
|
||||
if(aPlayerInfo[t].m_pPlayerInfo)
|
||||
{
|
||||
{
|
||||
// draw name
|
||||
int ID = aPlayerInfo[t].m_ClientID;
|
||||
char aName[64];
|
||||
str_format(aName, sizeof(aName), "%2d: %s", ID, g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : "");
|
||||
str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ID].m_aName : "");
|
||||
float w = TextRender()->TextWidth(0, 8.0f, aName, -1);
|
||||
TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split-PosSize), StartY+(t+1)*20.0f-3.0f, 8.0f, aName, -1);
|
||||
|
||||
CTextCursor Cursor;
|
||||
float x = min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split-PosSize);
|
||||
float y = StartY+(t+1)*20.0f-3.0f;
|
||||
TextRender()->SetCursor(&Cursor, x, y, 8.0f, TEXTFLAG_RENDER);
|
||||
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, ID);
|
||||
TextRender()->TextEx(&Cursor, aName, -1);
|
||||
|
||||
// draw tee
|
||||
CTeeRenderInfo Info = m_pClient->m_aClients[ID].m_RenderInfo;
|
||||
Info.m_Size = 18.0f;
|
||||
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
|
||||
vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20));
|
||||
Info.m_Size = 18.0f;
|
||||
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
|
||||
vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20));
|
||||
}
|
||||
|
||||
// draw position
|
||||
|
@ -314,7 +328,7 @@ void CHud::RenderWarmupTimer()
|
|||
float FontSize = 20.0f;
|
||||
float w = 0.0f;
|
||||
const char *pText = Localize("Warmup");
|
||||
|
||||
|
||||
if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10)
|
||||
{
|
||||
w = TextRender()->TextWidth(0, FontSize, pText, -1);
|
||||
|
@ -325,7 +339,7 @@ void CHud::RenderWarmupTimer()
|
|||
TextRender()->TextColor(1, 1, 0.5f, 1);
|
||||
TextRender()->Text(0x0, 10, 45, 8, pText, -1);
|
||||
}
|
||||
|
||||
|
||||
FontSize = 16.0f;
|
||||
if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0)
|
||||
{
|
||||
|
@ -348,7 +362,7 @@ void CHud::RenderWarmupTimer()
|
|||
else
|
||||
str_format(aBuf, sizeof(aBuf), "%d", round_to_int(Seconds));
|
||||
}
|
||||
|
||||
|
||||
if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10)
|
||||
{
|
||||
w = TextRender()->TextWidth(0, FontSize, aBuf, -1);
|
||||
|
@ -452,7 +466,8 @@ void CHud::RenderCursor()
|
|||
if(!m_pClient->m_Snap.m_pLocalCharacter || Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
||||
return;
|
||||
|
||||
RenderTools()->MapScreenToGroup(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y, Layers()->GameGroup(), m_pClient->m_pCamera->m_Zoom);
|
||||
vec2 Pos = *m_pClient->m_pCamera->GetCenter();
|
||||
RenderTools()->MapScreenToGroup(Pos.x, Pos.y, Layers()->GameGroup(), m_pClient->m_pCamera->GetZoom());
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
|
||||
|
@ -463,6 +478,75 @@ void CHud::RenderCursor()
|
|||
Graphics()->QuadsEnd();
|
||||
}
|
||||
|
||||
void CHud::RenderNinjaBar(float x, float y, float Progress)
|
||||
{
|
||||
Progress = clamp(Progress, 0.0f, 1.0f);
|
||||
const float EndWidth = 6.0f;
|
||||
const float BarHeight = 12.0f;
|
||||
const float WholeBarWidth = 120.f;
|
||||
const float MiddleBarWidth = WholeBarWidth - (EndWidth * 2.0f);
|
||||
|
||||
IGraphics::CQuadItem QuadStartFull(x, y, EndWidth, BarHeight);
|
||||
RenderTools()->SelectSprite(&g_pData->m_aSprites[SPRITE_NINJA_BAR_FULL_LEFT]);
|
||||
Graphics()->QuadsDrawTL(&QuadStartFull, 1);
|
||||
x += EndWidth;
|
||||
|
||||
const float FullBarWidth = MiddleBarWidth * Progress;
|
||||
const float EmptyBarWidth = MiddleBarWidth - FullBarWidth;
|
||||
|
||||
// full bar
|
||||
IGraphics::CQuadItem QuadFull(x, y, FullBarWidth, BarHeight);
|
||||
|
||||
CDataSprite SpriteBarFull = g_pData->m_aSprites[SPRITE_NINJA_BAR_FULL];
|
||||
// prevent pixel puree, select only a small slice
|
||||
if(Progress < 0.1f)
|
||||
{
|
||||
int spx = SpriteBarFull.m_X;
|
||||
int spy = SpriteBarFull.m_Y;
|
||||
float w = SpriteBarFull.m_W * 0.1f; // magic here
|
||||
int h = SpriteBarFull.m_H;
|
||||
int cx = SpriteBarFull.m_pSet->m_Gridx;
|
||||
int cy = SpriteBarFull.m_pSet->m_Gridy;
|
||||
float x1 = spx/(float)cx;
|
||||
float x2 = (spx+w-1/32.0f)/(float)cx;
|
||||
float y1 = spy/(float)cy;
|
||||
float y2 = (spy+h-1/32.0f)/(float)cy;
|
||||
|
||||
Graphics()->QuadsSetSubset(x1, y1, x2, y2);
|
||||
}
|
||||
else
|
||||
RenderTools()->SelectSprite(&SpriteBarFull);
|
||||
|
||||
Graphics()->QuadsDrawTL(&QuadFull, 1);
|
||||
|
||||
// empty bar
|
||||
// select the middle portion of the sprite so we don't get edge bleeding
|
||||
const CDataSprite SpriteBarEmpty = g_pData->m_aSprites[SPRITE_NINJA_BAR_EMPTY];
|
||||
{
|
||||
float spx = SpriteBarEmpty.m_X + 0.1f;
|
||||
float spy = SpriteBarEmpty.m_Y;
|
||||
float w = SpriteBarEmpty.m_W * 0.5f;
|
||||
int h = SpriteBarEmpty.m_H;
|
||||
int cx = SpriteBarEmpty.m_pSet->m_Gridx;
|
||||
int cy = SpriteBarEmpty.m_pSet->m_Gridy;
|
||||
float x1 = spx/(float)cx;
|
||||
float x2 = (spx+w-1/32.0f)/(float)cx;
|
||||
float y1 = spy/(float)cy;
|
||||
float y2 = (spy+h-1/32.0f)/(float)cy;
|
||||
|
||||
Graphics()->QuadsSetSubset(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
IGraphics::CQuadItem QuadEmpty(x + FullBarWidth, y, EmptyBarWidth, BarHeight);
|
||||
Graphics()->QuadsDrawTL(&QuadEmpty, 1);
|
||||
|
||||
x += MiddleBarWidth;
|
||||
|
||||
IGraphics::CQuadItem QuadEndEmpty(x, y, EndWidth, BarHeight);
|
||||
RenderTools()->SelectSprite(&g_pData->m_aSprites[SPRITE_NINJA_BAR_EMPTY_RIGHT]);
|
||||
Graphics()->QuadsDrawTL(&QuadEndEmpty, 1);
|
||||
}
|
||||
|
||||
void CHud::RenderHealthAndAmmo(const CNetObj_Character *pCharacter)
|
||||
{
|
||||
if(!pCharacter)
|
||||
|
@ -473,33 +557,32 @@ void CHud::RenderHealthAndAmmo(const CNetObj_Character *pCharacter)
|
|||
int i;
|
||||
IGraphics::CQuadItem Array[10];
|
||||
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
|
||||
Graphics()->WrapClamp();
|
||||
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// render ammo
|
||||
if(pCharacter->m_Weapon == WEAPON_NINJA)
|
||||
{
|
||||
CUIRect Rect = {x, y+24.0f, 118.0f, 10.0f};
|
||||
RenderTools()->DrawUIRect(&Rect, vec4(0.8f, 0.8f, 0.8f, 0.5f), 0, 0.0f);
|
||||
|
||||
int Max = g_pData->m_Weapons.m_Ninja.m_Duration * Client()->GameTickSpeed() / 1000;
|
||||
Rect.x = x+1.0f;
|
||||
Rect.y = y+25.0f;
|
||||
Rect.w = 116.0f * clamp(pCharacter->m_AmmoCount-Client()->GameTick(), 0, Max) / Max;
|
||||
Rect.h = 8.0f;
|
||||
RenderTools()->DrawUIRect(&Rect, vec4(0.9f, 0.2f, 0.2f, 0.85f), 0, 0.0f);
|
||||
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[WEAPON_NINJA].m_pSpriteBody);
|
||||
Array[0] = IGraphics::CQuadItem(x+40.0f,y+25, 32.0f, 8.0f);
|
||||
Graphics()->QuadsDrawTL(Array, 1);
|
||||
const int Max = g_pData->m_Weapons.m_Ninja.m_Duration * Client()->GameTickSpeed() / 1000;
|
||||
float NinjaProgress = clamp(pCharacter->m_AmmoCount-Client()->GameTick(), 0, Max) / (float)Max;
|
||||
RenderNinjaBar(x, y+24.f, NinjaProgress);
|
||||
}
|
||||
else
|
||||
{
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[pCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteProj);
|
||||
for(i = 0; i < min(pCharacter->m_AmmoCount, 10); i++)
|
||||
Array[i] = IGraphics::CQuadItem(x+i*12,y+24,10,10);
|
||||
if(pCharacter->m_Weapon == WEAPON_GRENADE)
|
||||
{
|
||||
for(i = 0; i < min(pCharacter->m_AmmoCount, 10); i++)
|
||||
Array[i] = IGraphics::CQuadItem(x+1+i*12, y+24, 10, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0; i < min(pCharacter->m_AmmoCount, 10); i++)
|
||||
Array[i] = IGraphics::CQuadItem(x+i*12, y+24, 12, 12);
|
||||
}
|
||||
Graphics()->QuadsDrawTL(Array, i);
|
||||
}
|
||||
|
||||
|
@ -508,28 +591,29 @@ void CHud::RenderHealthAndAmmo(const CNetObj_Character *pCharacter)
|
|||
// render health
|
||||
RenderTools()->SelectSprite(SPRITE_HEALTH_FULL);
|
||||
for(; h < min(pCharacter->m_Health, 10); h++)
|
||||
Array[h] = IGraphics::CQuadItem(x+h*12,y,10,10);
|
||||
Array[h] = IGraphics::CQuadItem(x+h*12,y,12,12);
|
||||
Graphics()->QuadsDrawTL(Array, h);
|
||||
|
||||
i = 0;
|
||||
RenderTools()->SelectSprite(SPRITE_HEALTH_EMPTY);
|
||||
for(; h < 10; h++)
|
||||
Array[i++] = IGraphics::CQuadItem(x+h*12,y,10,10);
|
||||
Array[i++] = IGraphics::CQuadItem(x+h*12,y,12,12);
|
||||
Graphics()->QuadsDrawTL(Array, i);
|
||||
|
||||
// render armor meter
|
||||
h = 0;
|
||||
RenderTools()->SelectSprite(SPRITE_ARMOR_FULL);
|
||||
for(; h < min(pCharacter->m_Armor, 10); h++)
|
||||
Array[h] = IGraphics::CQuadItem(x+h*12,y+12,10,10);
|
||||
Array[h] = IGraphics::CQuadItem(x+h*12,y+12,12,12);
|
||||
Graphics()->QuadsDrawTL(Array, h);
|
||||
|
||||
i = 0;
|
||||
RenderTools()->SelectSprite(SPRITE_ARMOR_EMPTY);
|
||||
for(; h < 10; h++)
|
||||
Array[i++] = IGraphics::CQuadItem(x+h*12,y+12,10,10);
|
||||
Array[i++] = IGraphics::CQuadItem(x+h*12,y+12,12,12);
|
||||
Graphics()->QuadsDrawTL(Array, i);
|
||||
Graphics()->QuadsEnd();
|
||||
Graphics()->WrapNormal();
|
||||
}
|
||||
|
||||
void CHud::RenderSpectatorHud()
|
||||
|
@ -540,28 +624,41 @@ void CHud::RenderSpectatorHud()
|
|||
|
||||
// draw the text
|
||||
char aName[64];
|
||||
str_format(aName, sizeof(aName), "%2d: %s", m_pClient->m_Snap.m_SpecInfo.m_SpectatorID, g_Config.m_ClShowsocial ? m_pClient->m_aClients[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID].m_aName : "");
|
||||
const int SpecID = m_pClient->m_Snap.m_SpecInfo.m_SpectatorID;
|
||||
const int SpecMode = m_pClient->m_Snap.m_SpecInfo.m_SpecMode;
|
||||
str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID].m_aName : "");
|
||||
char aBuf[128];
|
||||
switch(m_pClient->m_Snap.m_SpecInfo.m_SpecMode)
|
||||
|
||||
CTextCursor Cursor;
|
||||
TextRender()->SetCursor(&Cursor, m_Width-174.0f, m_Height-13.0f, 8.0f, TEXTFLAG_RENDER);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%s: ", Localize("Spectate"));
|
||||
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||
|
||||
switch(SpecMode)
|
||||
{
|
||||
case SPEC_FREEVIEW:
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Spectate"), Localize("Free-View"));
|
||||
str_format(aBuf, sizeof(aBuf), "%s", Localize("Free-View"));
|
||||
break;
|
||||
case SPEC_PLAYER:
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Spectate"), aName);
|
||||
str_format(aBuf, sizeof(aBuf), "%s", aName);
|
||||
break;
|
||||
case SPEC_FLAGRED:
|
||||
case SPEC_FLAGBLUE:
|
||||
char aFlag[64];
|
||||
str_format(aFlag, sizeof(aFlag), m_pClient->m_Snap.m_SpecInfo.m_SpecMode == SPEC_FLAGRED ? Localize("red flag") : Localize("blue flag"));
|
||||
str_format(aFlag, sizeof(aFlag), SpecMode == SPEC_FLAGRED ? Localize("red flag") : Localize("blue flag"));
|
||||
|
||||
if(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID != -1)
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s (%s)", Localize("Spectate"), aFlag, aName);
|
||||
if(SpecID != -1)
|
||||
str_format(aBuf, sizeof(aBuf), "%s (%s)", aFlag, aName);
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Spectate"), aFlag);
|
||||
str_format(aBuf, sizeof(aBuf), "%s", aFlag);
|
||||
break;
|
||||
}
|
||||
TextRender()->Text(0, m_Width-174.0f, m_Height-13.0f, 8.0f, aBuf, -1);
|
||||
|
||||
if(SpecMode == SPEC_PLAYER || SpecID != -1)
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, SpecID);
|
||||
|
||||
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||
}
|
||||
|
||||
void CHud::OnRender()
|
||||
|
|
|
@ -16,6 +16,7 @@ class CHud : public CComponent
|
|||
void RenderConnectionWarning();
|
||||
void RenderTeambalanceWarning();
|
||||
void RenderVoting();
|
||||
void RenderNinjaBar(float x, float y, float Progress);
|
||||
void RenderHealthAndAmmo(const CNetObj_Character *pCharacter);
|
||||
void RenderGameTimer();
|
||||
void RenderPauseTimer();
|
||||
|
|
|
@ -27,11 +27,11 @@ void CKillMessages::OnMessage(int MsgType, void *pRawMsg)
|
|||
CKillMsg Kill;
|
||||
Kill.m_VictimID = pMsg->m_Victim;
|
||||
Kill.m_VictimTeam = m_pClient->m_aClients[Kill.m_VictimID].m_Team;
|
||||
str_format(Kill.m_aVictimName, sizeof(Kill.m_aVictimName), "%2d: %s", pMsg->m_Victim, g_Config.m_ClShowsocial ? m_pClient->m_aClients[Kill.m_VictimID].m_aName : "");
|
||||
str_format(Kill.m_aVictimName, sizeof(Kill.m_aVictimName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[Kill.m_VictimID].m_aName : "");
|
||||
Kill.m_VictimRenderInfo = m_pClient->m_aClients[Kill.m_VictimID].m_RenderInfo;
|
||||
Kill.m_KillerID = pMsg->m_Killer;
|
||||
Kill.m_KillerTeam = m_pClient->m_aClients[Kill.m_KillerID].m_Team;
|
||||
str_format(Kill.m_aKillerName, sizeof(Kill.m_aKillerName), "%2d: %s", pMsg->m_Killer, g_Config.m_ClShowsocial ? m_pClient->m_aClients[Kill.m_KillerID].m_aName : "");
|
||||
str_format(Kill.m_aKillerName, sizeof(Kill.m_aKillerName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[Kill.m_KillerID].m_aName : "");
|
||||
Kill.m_KillerRenderInfo = m_pClient->m_aClients[Kill.m_KillerID].m_RenderInfo;
|
||||
Kill.m_Weapon = pMsg->m_Weapon;
|
||||
Kill.m_ModeSpecial = pMsg->m_ModeSpecial;
|
||||
|
@ -59,14 +59,18 @@ void CKillMessages::OnRender()
|
|||
continue;
|
||||
|
||||
float FontSize = 36.0f;
|
||||
float KillerNameW = TextRender()->TextWidth(0, FontSize, m_aKillmsgs[r].m_aKillerName, -1);
|
||||
float VictimNameW = TextRender()->TextWidth(0, FontSize, m_aKillmsgs[r].m_aVictimName, -1);
|
||||
float KillerNameW = TextRender()->TextWidth(0, FontSize, m_aKillmsgs[r].m_aKillerName, -1) + RenderTools()->GetClientIdRectSize(FontSize);
|
||||
float VictimNameW = TextRender()->TextWidth(0, FontSize, m_aKillmsgs[r].m_aVictimName, -1) + RenderTools()->GetClientIdRectSize(FontSize);
|
||||
|
||||
float x = StartX;
|
||||
|
||||
// render victim name
|
||||
x -= VictimNameW;
|
||||
TextRender()->Text(0, x, y, FontSize, m_aKillmsgs[r].m_aVictimName, -1);
|
||||
CTextCursor Cursor;
|
||||
TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
|
||||
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, m_aKillmsgs[r].m_VictimID);
|
||||
TextRender()->TextEx(&Cursor, m_aKillmsgs[r].m_aVictimName, -1);
|
||||
|
||||
// render victim tee
|
||||
x -= 24.0f;
|
||||
|
@ -135,7 +139,10 @@ void CKillMessages::OnRender()
|
|||
|
||||
// render killer name
|
||||
x -= KillerNameW;
|
||||
TextRender()->Text(0, x, y, FontSize, m_aKillmsgs[r].m_aKillerName, -1);
|
||||
TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
|
||||
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, m_aKillmsgs[r].m_KillerID);
|
||||
TextRender()->TextEx(&Cursor, m_aKillmsgs[r].m_aKillerName, -1);
|
||||
}
|
||||
|
||||
y += 46.0f;
|
||||
|
|
|
@ -28,18 +28,39 @@ CMapLayers::CMapLayers(int t)
|
|||
m_EnvelopeUpdate = false;
|
||||
m_pMenuMap = 0;
|
||||
m_pMenuLayers = 0;
|
||||
m_OnlineStartTime = 0;
|
||||
}
|
||||
|
||||
void CMapLayers::OnStateChange(int NewState, int OldState)
|
||||
{
|
||||
if(NewState == IClient::STATE_ONLINE)
|
||||
m_OnlineStartTime = Client()->LocalTime(); // reset time for non-scynchronized envelopes
|
||||
}
|
||||
|
||||
void CMapLayers::LoadBackgroundMap()
|
||||
{
|
||||
if(!g_Config.m_ClShowMenuMap)
|
||||
return;
|
||||
|
||||
int HourOfTheDay = time_houroftheday();
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), "ui/%s_%s.map", g_Config.m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "day" : "night");
|
||||
// check for the appropriate day/night map
|
||||
str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", g_Config.m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "day" : "night");
|
||||
if(!m_pMenuMap->Load(aBuf, m_pClient->Storage()))
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "map '%s' not found", g_Config.m_ClMenuMap);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf);
|
||||
return;
|
||||
// fall back on generic map
|
||||
str_format(aBuf, sizeof(aBuf), "ui/themes/%s.map", g_Config.m_ClMenuMap);
|
||||
if(!m_pMenuMap->Load(aBuf, m_pClient->Storage()))
|
||||
{
|
||||
// fall back on day/night alternative map
|
||||
str_format(aBuf, sizeof(aBuf), "ui/themes/%s_%s.map", g_Config.m_ClMenuMap, (HourOfTheDay >= 6 && HourOfTheDay < 18) ? "night" : "day");
|
||||
if(!m_pMenuMap->Load(aBuf, m_pClient->Storage()))
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "map '%s' not found", g_Config.m_ClMenuMap);
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client", aBuf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "loaded map '%s'", g_Config.m_ClMenuMap);
|
||||
|
@ -89,7 +110,7 @@ void CMapLayers::LoadEnvPoints(const CLayers *pLayers, array<CEnvPoint>& lEnvPoi
|
|||
pLayers->Map()->GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num);
|
||||
if(!Num)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
for(int env = 0; env < Num; env++)
|
||||
{
|
||||
|
@ -167,14 +188,13 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
|
|||
if(Env >= Num)
|
||||
return;
|
||||
|
||||
CMapItemEnvelope *pItem = (CMapItemEnvelope *)pLayers->Map()->GetItem(Start+Env, 0, 0);
|
||||
CMapItemEnvelope *pItem = (CMapItemEnvelope *)pLayers->Map()->GetItem(Start+Env, 0, 0);
|
||||
|
||||
static float s_Time = 0.0f;
|
||||
static float s_LastLocalTime = pThis->Client()->LocalTime();
|
||||
float Time = 0.0f;
|
||||
if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
||||
{
|
||||
const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo();
|
||||
|
||||
|
||||
if(!pInfo->m_Paused || pThis->m_EnvelopeUpdate)
|
||||
{
|
||||
if(pThis->m_CurrentLocalTick != pInfo->m_CurrentTick)
|
||||
|
@ -183,12 +203,12 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
|
|||
pThis->m_CurrentLocalTick = pInfo->m_CurrentTick;
|
||||
}
|
||||
|
||||
s_Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(),
|
||||
Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(),
|
||||
pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(),
|
||||
pThis->Client()->IntraGameTick());
|
||||
}
|
||||
|
||||
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
|
||||
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels);
|
||||
}
|
||||
else if(pThis->Client()->State() != IClient::STATE_OFFLINE)
|
||||
{
|
||||
|
@ -196,20 +216,20 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
|
|||
{
|
||||
if(pItem->m_Version < 2 || pItem->m_Synchronized)
|
||||
{
|
||||
s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / (float)pThis->Client()->GameTickSpeed(),
|
||||
Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / (float)pThis->Client()->GameTickSpeed(),
|
||||
(pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameData->m_GameStartTick) / (float)pThis->Client()->GameTickSpeed(),
|
||||
pThis->Client()->IntraGameTick());
|
||||
}
|
||||
else
|
||||
s_Time += pThis->Client()->LocalTime()-s_LastLocalTime;
|
||||
Time = pThis->Client()->LocalTime()-pThis->m_OnlineStartTime;
|
||||
}
|
||||
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
|
||||
s_LastLocalTime = pThis->Client()->LocalTime();
|
||||
|
||||
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_Time = pThis->Client()->LocalTime();
|
||||
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
|
||||
Time = pThis->Client()->LocalTime();
|
||||
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,7 +250,7 @@ void CMapLayers::OnRender()
|
|||
CUIRect Screen;
|
||||
Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h);
|
||||
|
||||
vec2 Center = m_pClient->m_pCamera->m_Center;
|
||||
vec2 Center = *m_pClient->m_pCamera->GetCenter();
|
||||
|
||||
bool PassedGameLayer = false;
|
||||
|
||||
|
@ -242,13 +262,13 @@ void CMapLayers::OnRender()
|
|||
{
|
||||
// set clipping
|
||||
float Points[4];
|
||||
RenderTools()->MapScreenToGroup(Center.x, Center.y, pLayers->GameGroup(), m_pClient->m_pCamera->m_Zoom);
|
||||
RenderTools()->MapScreenToGroup(Center.x, Center.y, pLayers->GameGroup(), m_pClient->m_pCamera->GetZoom());
|
||||
Graphics()->GetScreen(&Points[0], &Points[1], &Points[2], &Points[3]);
|
||||
float x0 = (pGroup->m_ClipX - Points[0]) / (Points[2]-Points[0]);
|
||||
float y0 = (pGroup->m_ClipY - Points[1]) / (Points[3]-Points[1]);
|
||||
float x1 = ((pGroup->m_ClipX+pGroup->m_ClipW) - Points[0]) / (Points[2]-Points[0]);
|
||||
float y1 = ((pGroup->m_ClipY+pGroup->m_ClipH) - Points[1]) / (Points[3]-Points[1]);
|
||||
|
||||
|
||||
if(x1 < 0.0f || x0 > 1.0f || y1 < 0.0f || y0 > 1.0f)
|
||||
continue;
|
||||
|
||||
|
@ -256,7 +276,7 @@ void CMapLayers::OnRender()
|
|||
(int)((x1-x0)*Graphics()->ScreenWidth()), (int)((y1-y0)*Graphics()->ScreenHeight()));
|
||||
}
|
||||
|
||||
RenderTools()->MapScreenToGroup(Center.x, Center.y, pGroup, m_pClient->m_pCamera->m_Zoom);
|
||||
RenderTools()->MapScreenToGroup(Center.x, Center.y, pGroup, m_pClient->m_pCamera->GetZoom());
|
||||
|
||||
for(int l = 0; l < pGroup->m_NumLayers; l++)
|
||||
{
|
||||
|
@ -366,6 +386,7 @@ void CMapLayers::ConchainBackgroundMap(IConsole::IResult *pResult, void *pUserDa
|
|||
void CMapLayers::OnConsoleInit()
|
||||
{
|
||||
Console()->Chain("cl_menu_map", ConchainBackgroundMap, this);
|
||||
Console()->Chain("cl_show_menu_map", ConchainBackgroundMap, this);
|
||||
}
|
||||
|
||||
void CMapLayers::BackgroundMapUpdate()
|
||||
|
|
|
@ -13,6 +13,7 @@ class CMapLayers : public CComponent
|
|||
int m_Type;
|
||||
int m_CurrentLocalTick;
|
||||
int m_LastLocalTick;
|
||||
float m_OnlineStartTime;
|
||||
bool m_EnvelopeUpdate;
|
||||
|
||||
array<CEnvPoint> m_lEnvPoints;
|
||||
|
@ -20,8 +21,8 @@ class CMapLayers : public CComponent
|
|||
|
||||
static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser);
|
||||
|
||||
void LoadBackgroundMap();
|
||||
void LoadEnvPoints(const CLayers *pLayers, array<CEnvPoint>& lEnvPoints);
|
||||
void LoadBackgroundMap();
|
||||
|
||||
public:
|
||||
enum
|
||||
|
@ -31,6 +32,7 @@ public:
|
|||
};
|
||||
|
||||
CMapLayers(int Type);
|
||||
virtual void OnStateChange(int NewState, int OldState);
|
||||
virtual void OnInit();
|
||||
virtual void OnRender();
|
||||
virtual void OnMapLoad();
|
||||
|
|
|
@ -34,8 +34,9 @@
|
|||
#include "skins.h"
|
||||
|
||||
float CMenus::ms_ButtonHeight = 25.0f;
|
||||
float CMenus::ms_ListheaderHeight = 20.0f;
|
||||
float CMenus::ms_ListheaderHeight = 17.0f;
|
||||
float CMenus::ms_FontmodHeight = 0.8f;
|
||||
float CMenus::ms_BackgroundAlpha = 0.25f;
|
||||
|
||||
|
||||
CMenus::CMenus()
|
||||
|
@ -44,6 +45,9 @@ CMenus::CMenus()
|
|||
m_NextPopup = POPUP_NONE;
|
||||
m_ActivePage = PAGE_INTERNET;
|
||||
m_GamePage = PAGE_GAME;
|
||||
m_SidebarTab = 0;
|
||||
m_SidebarActive = true;
|
||||
m_ShowServerDetails = true;
|
||||
|
||||
m_NeedRestartGraphics = false;
|
||||
m_NeedRestartSound = false;
|
||||
|
@ -58,38 +62,36 @@ CMenus::CMenus()
|
|||
|
||||
SetMenuPage(PAGE_START);
|
||||
|
||||
m_InfoMode = false;
|
||||
m_PopupActive = false;
|
||||
|
||||
m_EscapePressed = false;
|
||||
m_EnterPressed = false;
|
||||
m_TabPressed = false;
|
||||
m_DeletePressed = false;
|
||||
m_UpArrowPressed = false;
|
||||
m_DownArrowPressed = false;
|
||||
|
||||
m_LastInput = time_get();
|
||||
|
||||
str_copy(m_aCurrentDemoFolder, "demos", sizeof(m_aCurrentDemoFolder));
|
||||
m_aCallvoteReason[0] = 0;
|
||||
|
||||
m_FriendlistSelectedIndex = -1;
|
||||
|
||||
m_SelectedFilter = 0;
|
||||
|
||||
m_SelectedServer.m_Filter = -1;
|
||||
m_SelectedServer.m_Index = -1;
|
||||
m_ActiveListBox = ACTLB_THEME;
|
||||
}
|
||||
|
||||
float CMenus::ButtonFade(CButtonContainer *pBC, float Seconds, int Checked)
|
||||
{
|
||||
if (UI()->HotItem() == pBC->GetID() || Checked)
|
||||
if(UI()->HotItem() == pBC->GetID() || Checked)
|
||||
{
|
||||
pBC->m_FadeStartTime = Client()->LocalTime();
|
||||
return Seconds;
|
||||
}
|
||||
else if (pBC->m_FadeStartTime + Seconds > Client()->LocalTime())
|
||||
{
|
||||
return pBC->m_FadeStartTime + Seconds - Client()->LocalTime();
|
||||
}
|
||||
return 0.0f;
|
||||
|
||||
return max(0.0f, pBC->m_FadeStartTime - Client()->LocalTime() + Seconds);
|
||||
}
|
||||
|
||||
int CMenus::DoIcon(int ImageId, int SpriteId, const CUIRect *pRect)
|
||||
|
@ -216,24 +218,38 @@ int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, co
|
|||
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
|
||||
}
|
||||
|
||||
int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, int Corners, float r, float FontFactor)
|
||||
int CMenus::DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, float Alpha, float FontAlpha, int Corners, float r, float FontFactor)
|
||||
{
|
||||
if(UI()->MouseInside(pRect))
|
||||
Alpha = 1.0f;
|
||||
float Seconds = 0.6f; // 0.6 seconds for fade
|
||||
float Fade = ButtonFade(pBC, Seconds, Checked);
|
||||
float FadeVal = Fade/Seconds;
|
||||
float FadeVal = (Fade/Seconds)*FontAlpha;
|
||||
|
||||
RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f+FadeVal*0.5f), Corners, r);
|
||||
RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f*Alpha+FadeVal*0.5f), Corners, r);
|
||||
CUIRect Temp;
|
||||
pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp);
|
||||
Temp.HMargin((Temp.h*FontFactor)/2.0f, &Temp);
|
||||
TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, 1.0f);
|
||||
TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f);
|
||||
TextRender()->TextColor(1.0f-FadeVal, 1.0f-FadeVal, 1.0f-FadeVal, FontAlpha);
|
||||
TextRender()->TextOutlineColor(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f*FontAlpha);
|
||||
UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER);
|
||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
return UI()->DoButtonLogic(pBC->GetID(), pText, Checked, pRect);
|
||||
}
|
||||
|
||||
void CMenus::DoButton_MenuTabTop_Dummy(const char *pText, int Checked, const CUIRect *pRect, float Alpha)
|
||||
{
|
||||
RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f*Alpha), CUI::CORNER_ALL, 5.0f);
|
||||
CUIRect Temp;
|
||||
pRect->HMargin(pRect->h >= 20.0f ? 2.0f : 1.0f, &Temp);
|
||||
TextRender()->TextColor(0.15f, 0.15f, 0.15f, Alpha);
|
||||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.25f*Alpha);
|
||||
UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, CUI::ALIGN_CENTER);
|
||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
}
|
||||
|
||||
int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
|
||||
//void CMenus::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
|
||||
{
|
||||
|
@ -304,7 +320,7 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c
|
|||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
|
||||
t.y += 2.0f; // lame fix
|
||||
t.y += 1.0f; // lame fix
|
||||
UI()->DoLabel(&c, pBoxText, pRect->h*ms_FontmodHeight*0.6f, CUI::ALIGN_CENTER);
|
||||
UI()->DoLabel(&t, pText, pRect->h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
return UI()->DoButtonLogic(pID, pText, 0, pRect);
|
||||
|
@ -322,18 +338,19 @@ int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Che
|
|||
return DoButton_CheckBox_Common(pID, pText, aBuf, pRect);
|
||||
}
|
||||
|
||||
int CMenus::DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, const CUIRect *pRect, int Corners, float r, bool Fade)
|
||||
int CMenus::DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, bool Checked, const CUIRect *pRect, int Corners, float r, bool Fade)
|
||||
{
|
||||
float Seconds = 0.6f; // 0.6 seconds for fade
|
||||
float FadeVal = ButtonFade(pBC, Seconds)/Seconds;
|
||||
float FadeVal = Fade ? ButtonFade(pBC, Seconds, Checked) / Seconds : 0.0f;
|
||||
|
||||
RenderTools()->DrawUIRect(pRect, vec4(0.0f + FadeVal, 0.0f + FadeVal, 0.0f + FadeVal, 0.25f + FadeVal * 0.5f), Corners, r);
|
||||
|
||||
CUIRect Icon = *pRect;
|
||||
if(Icon.w > Icon.h)
|
||||
Icon.VMargin((Icon.w - Icon.h) / 2, &Icon);
|
||||
else if(Icon.w < Icon.h)
|
||||
Icon.HMargin((Icon.h - Icon.w) / 2, &Icon);
|
||||
Icon.Margin(2.0f, &Icon);
|
||||
|
||||
if(Fade)
|
||||
RenderTools()->DrawUIRect(pRect, vec4(0.0f+FadeVal, 0.0f+FadeVal, 0.0f+FadeVal, 0.25f+FadeVal*0.5f), Corners, r);
|
||||
else
|
||||
RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), Corners, r);
|
||||
Graphics()->TextureSet(g_pData->m_aImages[ImageID].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
@ -634,6 +651,50 @@ float CMenus::DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr,
|
|||
return HeaderHeight;
|
||||
}
|
||||
|
||||
float CMenus::DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool* pActive)
|
||||
{
|
||||
CUIRect View = *pRect;
|
||||
CUIRect Header, Label;
|
||||
|
||||
bool Active = *pActive;
|
||||
int Corners = Active ? CUI::CORNER_T : CUI::CORNER_ALL;
|
||||
|
||||
View.HSplitTop(HeaderHeight, &Header, &View);
|
||||
|
||||
// background
|
||||
RenderTools()->DrawUIRect(&Header, vec4(0.0f, 0.0f, 0.0f, 0.25f), Corners, 5.0f);
|
||||
|
||||
// render icon
|
||||
CUIRect Button;
|
||||
Header.VSplitLeft(Header.h, &Button, 0);
|
||||
Button.Margin(2.0f, &Button);
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_MENUICONS].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.0f, 1.0f, 1.0f, UI()->HotItem() == pID ? 1.0f : 0.6f);
|
||||
if(Active)
|
||||
RenderTools()->SelectSprite(SPRITE_MENU_EXPANDED);
|
||||
else
|
||||
RenderTools()->SelectSprite(SPRITE_MENU_COLLAPSED);
|
||||
IGraphics::CQuadItem QuadItem(Button.x, Button.y, Button.w, Button.h);
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
Graphics()->QuadsEnd();
|
||||
|
||||
// label
|
||||
Label = Header;
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, pStr, Header.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
|
||||
if(UI()->DoButtonLogic(pID, 0, 0, &Header))
|
||||
*pActive ^= 1;
|
||||
|
||||
// render content of expanded menu
|
||||
if(Active)
|
||||
return HeaderHeight + pfnCallback(View, this);
|
||||
|
||||
return HeaderHeight;
|
||||
}
|
||||
|
||||
void CMenus::DoInfoBox(const CUIRect *pRect, const char *pLabel, const char *pValue)
|
||||
{
|
||||
RenderTools()->DrawUIRect(pRect, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
@ -913,8 +974,8 @@ CMenus::CListboxItem CMenus::UiDoListboxNextItem(CListBoxState* pState, const vo
|
|||
else
|
||||
{
|
||||
int NewIndex = -1;
|
||||
if(Input()->KeyPress(KEY_DOWN)) NewIndex = pState->m_ListBoxNewSelected + 1;
|
||||
if(Input()->KeyPress(KEY_UP)) NewIndex = pState->m_ListBoxNewSelected - 1;
|
||||
if(m_DownArrowPressed) NewIndex = pState->m_ListBoxNewSelected + 1;
|
||||
if(m_UpArrowPressed) NewIndex = pState->m_ListBoxNewSelected - 1;
|
||||
if(NewIndex > -1 && NewIndex < pState->m_ListBoxNumItems)
|
||||
{
|
||||
// scroll
|
||||
|
@ -967,7 +1028,7 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in
|
|||
static const void *pGrabbedID = 0;
|
||||
static bool MouseReleased = true;
|
||||
static int ButtonUsed = 0;
|
||||
int Inside = UI()->MouseInside(pRect);
|
||||
int Inside = UI()->MouseInside(pRect) && UI()->MouseInsideClip();
|
||||
int NewKey = Key;
|
||||
*NewModifier = Modifier;
|
||||
|
||||
|
@ -1037,10 +1098,12 @@ int CMenus::DoKeyReader(CButtonContainer *pBC, const CUIRect *pRect, int Key, in
|
|||
return NewKey;
|
||||
}
|
||||
|
||||
void CMenus::RenderMenubar(CUIRect r)
|
||||
void CMenus::RenderMenubar(CUIRect Rect)
|
||||
{
|
||||
CUIRect Box = r;
|
||||
CUIRect Box;
|
||||
CUIRect Button;
|
||||
Rect.HSplitTop(60.0f, &Box, &Rect);
|
||||
const float InactiveAlpha = 0.25f;
|
||||
|
||||
m_ActivePage = m_MenuPage;
|
||||
int NewPage = -1;
|
||||
|
@ -1048,6 +1111,55 @@ void CMenus::RenderMenubar(CUIRect r)
|
|||
if(Client()->State() != IClient::STATE_OFFLINE)
|
||||
m_ActivePage = m_GamePage;
|
||||
|
||||
if(Client()->State() == IClient::STATE_ONLINE)
|
||||
{
|
||||
float Spacing = 3.0f;
|
||||
float ButtonWidth = (Box.w / 6.0f) - (Spacing*5.0) / 6.0f;
|
||||
float Alpha = 1.0f;
|
||||
if(m_GamePage == PAGE_SETTINGS)
|
||||
Alpha = InactiveAlpha;
|
||||
|
||||
// render header backgrounds
|
||||
CUIRect Left, Right;
|
||||
Box.VSplitLeft(ButtonWidth*4.0f + Spacing * 3.0f, &Left, 0);
|
||||
Box.VSplitRight(ButtonWidth, 0, &Right);
|
||||
RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
|
||||
Left.HSplitBottom(25.0f, 0, &Left);
|
||||
Right.HSplitBottom(25.0f, 0, &Right);
|
||||
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_GameButton;
|
||||
if(DoButton_MenuTabTop(&s_GameButton, Localize("Game"), m_ActivePage == PAGE_GAME, &Button, Alpha, Alpha))
|
||||
NewPage = PAGE_GAME;
|
||||
|
||||
Left.VSplitLeft(Spacing, 0, &Left); // little space
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_PlayersButton;
|
||||
if(DoButton_MenuTabTop(&s_PlayersButton, Localize("Players"), m_ActivePage == PAGE_PLAYERS, &Button, Alpha, Alpha))
|
||||
NewPage = PAGE_PLAYERS;
|
||||
|
||||
Left.VSplitLeft(Spacing, 0, &Left); // little space
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_ServerInfoButton;
|
||||
if(DoButton_MenuTabTop(&s_ServerInfoButton, Localize("Server info"), m_ActivePage == PAGE_SERVER_INFO, &Button, Alpha, Alpha))
|
||||
NewPage = PAGE_SERVER_INFO;
|
||||
|
||||
Left.VSplitLeft(Spacing, 0, &Left); // little space
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_CallVoteButton;
|
||||
if(DoButton_MenuTabTop(&s_CallVoteButton, Localize("Call vote"), m_ActivePage == PAGE_CALLVOTE, &Button, Alpha, Alpha))
|
||||
NewPage = PAGE_CALLVOTE;
|
||||
|
||||
static CButtonContainer s_SettingsButton;
|
||||
if(DoButton_MenuTabTop(&s_SettingsButton, Localize("Settings"), m_GamePage == PAGE_SETTINGS, &Right))
|
||||
NewPage = PAGE_SETTINGS;
|
||||
|
||||
Rect.HSplitTop(Spacing, 0, &Rect);
|
||||
Rect.HSplitTop(25.0f, &Box, &Rect);
|
||||
}
|
||||
|
||||
if((Client()->State() == IClient::STATE_OFFLINE && m_MenuPage == PAGE_SETTINGS) || (Client()->State() == IClient::STATE_ONLINE && m_GamePage == PAGE_SETTINGS))
|
||||
{
|
||||
if(Client()->State() == IClient::STATE_ONLINE && (g_Config.m_UiSettingsPage == SETTINGS_PLAYER || g_Config.m_UiSettingsPage == SETTINGS_TEE))
|
||||
|
@ -1056,77 +1168,93 @@ void CMenus::RenderMenubar(CUIRect r)
|
|||
}
|
||||
float Spacing = 3.0f;
|
||||
float ButtonWidth = (Box.w/6.0f)-(Spacing*5.0)/6.0f;
|
||||
float NotActiveAlpha = Client()->State() == IClient::STATE_ONLINE ? 0.5f : 1.0f;
|
||||
int Corners = Client()->State() == IClient::STATE_ONLINE ? CUI::CORNER_T : CUI::CORNER_ALL;
|
||||
|
||||
// render header background
|
||||
RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
if(Client()->State() == IClient::STATE_OFFLINE)
|
||||
RenderTools()->DrawUIRect4(&Box, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
|
||||
Box.HSplitBottom(25.0f, 0, &Box);
|
||||
|
||||
Box.VSplitLeft(ButtonWidth, &Button, &Box);
|
||||
static CButtonContainer s_GeneralButton;
|
||||
if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), g_Config.m_UiSettingsPage==SETTINGS_GENERAL, &Button))
|
||||
if(DoButton_MenuTabTop(&s_GeneralButton, Localize("General"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_GENERAL, &Button,
|
||||
g_Config.m_UiSettingsPage == SETTINGS_GENERAL ? 1.0f : NotActiveAlpha, 1.0f, Corners))
|
||||
{
|
||||
m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_GENERAL);
|
||||
g_Config.m_UiSettingsPage = SETTINGS_GENERAL;
|
||||
}
|
||||
|
||||
Box.VSplitLeft(Spacing, 0, &Box); // little space
|
||||
Box.VSplitLeft(ButtonWidth, &Button, &Box);
|
||||
static CButtonContainer s_PlayerButton;
|
||||
if(Client()->State() != IClient::STATE_ONLINE && DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), g_Config.m_UiSettingsPage == SETTINGS_PLAYER, &Button))
|
||||
if(Client()->State() == IClient::STATE_OFFLINE)
|
||||
{
|
||||
g_Config.m_UiSettingsPage = SETTINGS_PLAYER;
|
||||
static CButtonContainer s_PlayerButton;
|
||||
if(DoButton_MenuTabTop(&s_PlayerButton, Localize("Player"), g_Config.m_UiSettingsPage == SETTINGS_PLAYER, &Button))
|
||||
{
|
||||
m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_PLAYER);
|
||||
g_Config.m_UiSettingsPage = SETTINGS_PLAYER;
|
||||
}
|
||||
}
|
||||
|
||||
Box.VSplitLeft(Spacing, 0, &Box); // little space
|
||||
Box.VSplitLeft(ButtonWidth, &Button, &Box);
|
||||
static CButtonContainer s_TeeButton;
|
||||
if(Client()->State() != IClient::STATE_ONLINE && DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), g_Config.m_UiSettingsPage == SETTINGS_TEE, &Button))
|
||||
if(Client()->State() == IClient::STATE_OFFLINE)
|
||||
{
|
||||
g_Config.m_UiSettingsPage = SETTINGS_TEE;
|
||||
static CButtonContainer s_TeeButton;
|
||||
if(DoButton_MenuTabTop(&s_TeeButton, Localize("Tee"), g_Config.m_UiSettingsPage == SETTINGS_TEE, &Button))
|
||||
{
|
||||
m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_TEE);
|
||||
g_Config.m_UiSettingsPage = SETTINGS_TEE;
|
||||
}
|
||||
}
|
||||
|
||||
Box.VSplitLeft(Spacing, 0, &Box); // little space
|
||||
Box.VSplitLeft(ButtonWidth, &Button, &Box);
|
||||
static CButtonContainer s_ControlsButton;
|
||||
if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), g_Config.m_UiSettingsPage==SETTINGS_CONTROLS, &Button))
|
||||
if(DoButton_MenuTabTop(&s_ControlsButton, Localize("Controls"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_CONTROLS, &Button,
|
||||
g_Config.m_UiSettingsPage == SETTINGS_CONTROLS ? 1.0f : NotActiveAlpha, 1.0f, Corners))
|
||||
{
|
||||
m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_CONTROLS);
|
||||
g_Config.m_UiSettingsPage = SETTINGS_CONTROLS;
|
||||
}
|
||||
|
||||
Box.VSplitLeft(Spacing, 0, &Box); // little space
|
||||
Box.VSplitLeft(ButtonWidth, &Button, &Box);
|
||||
static CButtonContainer s_GraphicsButton;
|
||||
if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), g_Config.m_UiSettingsPage==SETTINGS_GRAPHICS, &Button))
|
||||
if(DoButton_MenuTabTop(&s_GraphicsButton, Localize("Graphics"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_GRAPHICS, &Button,
|
||||
g_Config.m_UiSettingsPage == SETTINGS_GRAPHICS ? 1.0f : NotActiveAlpha, 1.0f, Corners))
|
||||
{
|
||||
m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_GRAPHICS);
|
||||
g_Config.m_UiSettingsPage = SETTINGS_GRAPHICS;
|
||||
}
|
||||
|
||||
Box.VSplitLeft(Spacing, 0, &Box); // little space
|
||||
Box.VSplitLeft(ButtonWidth, &Button, &Box);
|
||||
static CButtonContainer s_SoundButton;
|
||||
if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), g_Config.m_UiSettingsPage==SETTINGS_SOUND, &Button))
|
||||
if(DoButton_MenuTabTop(&s_SoundButton, Localize("Sound"), Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiSettingsPage==SETTINGS_SOUND, &Button,
|
||||
g_Config.m_UiSettingsPage == SETTINGS_SOUND ? 1.0f : NotActiveAlpha, 1.0f, Corners))
|
||||
{
|
||||
m_pClient->m_pCamera->ChangePosition(CCamera::POS_SETTINGS_SOUND);
|
||||
g_Config.m_UiSettingsPage = SETTINGS_SOUND;
|
||||
}
|
||||
}
|
||||
else if(Client()->State() == IClient::STATE_OFFLINE)
|
||||
{
|
||||
// render menu tabs
|
||||
if(m_MenuPage >= PAGE_INTERNET && m_MenuPage <= PAGE_FRIENDS)
|
||||
if(m_MenuPage >= PAGE_INTERNET && m_MenuPage <= PAGE_LAN)
|
||||
{
|
||||
float Spacing = 3.0f;
|
||||
float ButtonWidth = (Box.w/6.0f)-(Spacing*5.0)/6.0f;
|
||||
|
||||
CUIRect Left, Right;
|
||||
CUIRect Left;
|
||||
Box.VSplitLeft(ButtonWidth*2.0f+Spacing, &Left, 0);
|
||||
Box.VSplitRight(ButtonWidth, 0, &Right);
|
||||
|
||||
// render header backgrounds
|
||||
RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
|
||||
|
||||
Left.HSplitBottom(25.0f, 0, &Left);
|
||||
Right.HSplitBottom(25.0f, 0, &Right);
|
||||
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_InternetButton;
|
||||
|
@ -1148,19 +1276,6 @@ void CMenus::RenderMenubar(CUIRect r)
|
|||
NewPage = PAGE_LAN;
|
||||
g_Config.m_UiBrowserPage = PAGE_LAN;
|
||||
}
|
||||
|
||||
char aBuf[32];
|
||||
if(m_BorwserPage == PAGE_BROWSER_BROWSER)
|
||||
str_copy(aBuf, Localize("Friends"), sizeof(aBuf));
|
||||
else if(m_BorwserPage == PAGE_BROWSER_FRIENDS)
|
||||
str_copy(aBuf, Localize("Browser"), sizeof(aBuf));
|
||||
static CButtonContainer s_FilterButton;
|
||||
if(DoButton_Menu(&s_FilterButton, aBuf, 0, &Right))
|
||||
{
|
||||
m_BorwserPage++;
|
||||
if(m_BorwserPage >= NUM_PAGE_BROWSER)
|
||||
m_BorwserPage = 0;
|
||||
}
|
||||
}
|
||||
else if(m_MenuPage == PAGE_DEMOS)
|
||||
{
|
||||
|
@ -1179,52 +1294,8 @@ void CMenus::RenderMenubar(CUIRect r)
|
|||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float Spacing = 3.0f;
|
||||
float ButtonWidth = (Box.w/6.0f)-(Spacing*5.0)/6.0f;
|
||||
|
||||
// render header backgrounds
|
||||
CUIRect Left, Right;
|
||||
Box.VSplitLeft(ButtonWidth*4.0f+Spacing*3.0f, &Left, 0);
|
||||
Box.VSplitRight(ButtonWidth, 0, &Right);
|
||||
RenderTools()->DrawUIRect4(&Left, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
RenderTools()->DrawUIRect4(&Right, vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.0f), vec4(0.0f, 0.0f, 0.0f, 0.25f), vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 5.0f);
|
||||
|
||||
Left.HSplitBottom(25.0f, 0, &Left);
|
||||
Right.HSplitBottom(25.0f, 0, &Right);
|
||||
|
||||
// online menus
|
||||
if(m_GamePage != PAGE_SETTINGS) // Game stuff
|
||||
{
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_GameButton;
|
||||
if(DoButton_MenuTabTop(&s_GameButton, Localize("Game"), m_ActivePage==PAGE_GAME, &Button))
|
||||
NewPage = PAGE_GAME;
|
||||
|
||||
Left.VSplitLeft(Spacing, 0, &Left); // little space
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_PlayersButton;
|
||||
if(DoButton_MenuTabTop(&s_PlayersButton, Localize("Players"), m_ActivePage==PAGE_PLAYERS, &Button))
|
||||
NewPage = PAGE_PLAYERS;
|
||||
|
||||
Left.VSplitLeft(Spacing, 0, &Left); // little space
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_ServerInfoButton;
|
||||
if(DoButton_MenuTabTop(&s_ServerInfoButton, Localize("Server info"), m_ActivePage==PAGE_SERVER_INFO, &Button))
|
||||
NewPage = PAGE_SERVER_INFO;
|
||||
|
||||
Left.VSplitLeft(Spacing, 0, &Left); // little space
|
||||
Left.VSplitLeft(ButtonWidth, &Button, &Left);
|
||||
static CButtonContainer s_CallVoteButton;
|
||||
if(DoButton_MenuTabTop(&s_CallVoteButton, Localize("Call vote"), m_ActivePage==PAGE_CALLVOTE, &Button))
|
||||
NewPage = PAGE_CALLVOTE;
|
||||
|
||||
static CButtonContainer s_SettingsButton;
|
||||
if(DoButton_MenuTabTop(&s_SettingsButton, Localize("Settings"), 0, &Right))
|
||||
NewPage = PAGE_SETTINGS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(NewPage != -1)
|
||||
{
|
||||
|
@ -1287,6 +1358,9 @@ void CMenus::RenderNews(CUIRect MainView)
|
|||
|
||||
void CMenus::RenderBackButton(CUIRect MainView)
|
||||
{
|
||||
if(Client()->State() != IClient::STATE_OFFLINE)
|
||||
return;
|
||||
|
||||
// same size like tabs in top but variables not really needed
|
||||
float Spacing = 3.0f;
|
||||
float ButtonWidth = (MainView.w/6.0f)-(Spacing*5.0)/6.0f;
|
||||
|
@ -1301,12 +1375,9 @@ void CMenus::RenderBackButton(CUIRect MainView)
|
|||
MainView.HSplitTop(25.0f, &MainView, 0);
|
||||
Button = MainView;
|
||||
static CButtonContainer s_MenuButton;
|
||||
if(DoButton_Menu(&s_MenuButton, Localize("Back"), 0, &Button) || (m_EscapePressed && Client()->State() != IClient::STATE_ONLINE))
|
||||
if(DoButton_Menu(&s_MenuButton, Localize("Back"), 0, &Button) || m_EscapePressed)
|
||||
{
|
||||
if(Client()->State() != IClient::STATE_OFFLINE)
|
||||
m_GamePage = PAGE_GAME;
|
||||
else
|
||||
SetMenuPage(PAGE_START);
|
||||
SetMenuPage(PAGE_START);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1584,8 +1655,11 @@ int CMenus::Render()
|
|||
else
|
||||
{
|
||||
// do tab bar
|
||||
float BarHeight = 60.0f;
|
||||
if(Client()->State() == IClient::STATE_ONLINE && m_GamePage == PAGE_SETTINGS)
|
||||
BarHeight += 3.0f + 25.0f;
|
||||
Screen.VMargin(Screen.w/2-365.0f, &MainView);
|
||||
MainView.HSplitTop(60.0f, &TabBar, &MainView);
|
||||
MainView.HSplitTop(BarHeight, &TabBar, &MainView);
|
||||
RenderMenubar(TabBar);
|
||||
|
||||
// news is not implemented yet
|
||||
|
@ -1594,14 +1668,28 @@ int CMenus::Render()
|
|||
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
|
||||
m_MenuPage = PAGE_INTERNET;
|
||||
}*/
|
||||
|
||||
// quit button
|
||||
CUIRect Button;
|
||||
float TopOffset = 35.0f;
|
||||
Screen.HSplitTop(TopOffset, &Button, 0);
|
||||
Button.VSplitRight(TopOffset - 3.0f, 0, &Button);
|
||||
static CButtonContainer s_QuitButton;
|
||||
if(DoButton_Menu(&s_QuitButton, "X", 0, &Button, 0, CUI::CORNER_BL))
|
||||
m_Popup = POPUP_QUIT;
|
||||
{
|
||||
CUIRect Button;
|
||||
float TopOffset = 27.0f;
|
||||
Screen.HSplitTop(TopOffset, &Button, 0);
|
||||
Button.VSplitRight(TopOffset/* - 3.0f*/, 0, &Button);
|
||||
static CButtonContainer s_QuitButton;
|
||||
|
||||
// draw red-blending button
|
||||
vec4 Color = mix(vec4(0.f, 0.f, 0.f, 0.25f), vec4(1.f/0xff*0xf9, 1.f/0xff*0x2b, 1.f/0xff*0x2b, 0.75f), ButtonFade(&s_QuitButton, 0.6f, 0)/0.6f);
|
||||
RenderTools()->DrawUIRect(&Button, Color, CUI::CORNER_BL, 5.0f);
|
||||
|
||||
// draw non-blending X
|
||||
CUIRect XText = Button;
|
||||
// XText.HMargin(Button.h>=20.0f?2.0f:1.0f, &XText);
|
||||
|
||||
UI()->DoLabel(&XText, "\xE2\x9C\x95", XText.h*ms_FontmodHeight, CUI::ALIGN_CENTER);
|
||||
if(UI()->DoButtonLogic(s_QuitButton.GetID(), "\xE2\x9C\x95", 0, &Button))
|
||||
// if(DoButton_SpriteCleanID(&s_QuitButton, IMAGE_FRIENDICONS, SPRITE_FRIEND_X_A, &Button, false))
|
||||
m_Popup = POPUP_QUIT;
|
||||
}
|
||||
|
||||
// render current page
|
||||
if(Client()->State() != IClient::STATE_OFFLINE)
|
||||
|
@ -1627,8 +1715,6 @@ int CMenus::Render()
|
|||
RenderServerbrowser(MainView);
|
||||
else if(m_MenuPage == PAGE_DEMOS)
|
||||
RenderDemoList(MainView);
|
||||
else if(m_MenuPage == PAGE_FRIENDS)
|
||||
RenderServerbrowser(MainView);
|
||||
else if(m_MenuPage == PAGE_SETTINGS)
|
||||
RenderSettings(MainView);
|
||||
}
|
||||
|
@ -2077,12 +2163,12 @@ int CMenus::Render()
|
|||
{
|
||||
m_Popup = POPUP_NONE;
|
||||
// remove friend
|
||||
if(m_FriendlistSelectedIndex >= 0)
|
||||
if(m_pDeleteFriend)
|
||||
{
|
||||
m_pClient->Friends()->RemoveFriend(m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_aName,
|
||||
m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_aClan);
|
||||
m_pClient->Friends()->RemoveFriend(m_pDeleteFriend->m_aName, m_pDeleteFriend->m_aClan);
|
||||
FriendlistOnUpdate();
|
||||
Client()->ServerBrowserUpdate();
|
||||
m_pDeleteFriend = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2263,8 +2349,14 @@ bool CMenus::OnInput(IInput::CEvent e)
|
|||
// special for popups
|
||||
if(e.m_Key == KEY_RETURN || e.m_Key == KEY_KP_ENTER)
|
||||
m_EnterPressed = true;
|
||||
else if(e.m_Key == KEY_TAB && !Input()->KeyPress(KEY_LALT) && !Input()->KeyPress(KEY_RALT))
|
||||
m_TabPressed = true;
|
||||
else if(e.m_Key == KEY_DELETE)
|
||||
m_DeletePressed = true;
|
||||
else if(e.m_Key == KEY_UP)
|
||||
m_UpArrowPressed = true;
|
||||
else if(e.m_Key == KEY_DOWN)
|
||||
m_DownArrowPressed = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2298,14 +2390,14 @@ void CMenus::OnConsoleInit()
|
|||
{
|
||||
// put it on top
|
||||
int Pos = m_lFilters.size();
|
||||
m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_STANDARD, "Teeworlds", ServerBrowser(), IServerBrowser::FILTER_COMPAT_VERSION | IServerBrowser::FILTER_PURE | IServerBrowser::FILTER_PURE_MAP | IServerBrowser::FILTER_PING, 999, -1, "", ""));
|
||||
m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_STANDARD, "Teeworlds", ServerBrowser()));
|
||||
for(; Pos > 0; --Pos)
|
||||
Move(true, Pos);
|
||||
}
|
||||
if(!FilterFav)
|
||||
m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_FAVORITES, Localize("Favorites"), ServerBrowser(), IServerBrowser::FILTER_FAVORITE | IServerBrowser::FILTER_PING, 999, -1, "", ""));
|
||||
m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_FAVORITES, Localize("Favorites"), ServerBrowser()));
|
||||
if(!FilterAll)
|
||||
m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_ALL, Localize("All"), ServerBrowser(), IServerBrowser::FILTER_PING, 999, -1, "", ""));
|
||||
m_lFilters.add(CBrowserFilter(CBrowserFilter::FILTER_ALL, Localize("All"), ServerBrowser()));
|
||||
}
|
||||
|
||||
void CMenus::OnShutdown()
|
||||
|
@ -2380,7 +2472,10 @@ void CMenus::OnRender()
|
|||
{
|
||||
m_EscapePressed = false;
|
||||
m_EnterPressed = false;
|
||||
m_TabPressed = false;
|
||||
m_DeletePressed = false;
|
||||
m_UpArrowPressed = false;
|
||||
m_DownArrowPressed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2405,11 +2500,13 @@ void CMenus::OnRender()
|
|||
|
||||
// render cursor
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id);
|
||||
Graphics()->WrapClamp();
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1,1,1,1);
|
||||
IGraphics::CQuadItem QuadItem(mx, my, 24, 24);
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
Graphics()->WrapNormal();
|
||||
|
||||
// render debug information
|
||||
if(g_Config.m_Debug)
|
||||
|
@ -2427,7 +2524,10 @@ void CMenus::OnRender()
|
|||
UI()->FinishCheck();
|
||||
m_EscapePressed = false;
|
||||
m_EnterPressed = false;
|
||||
m_TabPressed = false;
|
||||
m_DeletePressed = false;
|
||||
m_UpArrowPressed = false;
|
||||
m_DownArrowPressed = false;
|
||||
}
|
||||
|
||||
void CMenus::RenderBackground()
|
||||
|
@ -2518,9 +2618,9 @@ void CMenus::SetMenuPage(int NewPage) {
|
|||
{
|
||||
case PAGE_START: CameraPos = CCamera::POS_START; break;
|
||||
case PAGE_DEMOS: CameraPos = CCamera::POS_DEMOS; break;
|
||||
case PAGE_SETTINGS: CameraPos = CCamera::POS_SETTINGS; break;
|
||||
case PAGE_INTERNET:
|
||||
case PAGE_LAN: CameraPos = CCamera::POS_INTERNET;
|
||||
case PAGE_SETTINGS: CameraPos = CCamera::POS_SETTINGS_GENERAL+g_Config.m_UiSettingsPage; break;
|
||||
case PAGE_INTERNET: CameraPos = CCamera::POS_INTERNET; break;
|
||||
case PAGE_LAN: CameraPos = CCamera::POS_LAN;
|
||||
}
|
||||
|
||||
if(CameraPos != -1 && m_pClient && m_pClient->m_pCamera)
|
||||
|
|
|
@ -48,13 +48,14 @@ private:
|
|||
|
||||
|
||||
int DoButton_DemoPlayer(CButtonContainer *pBC, const char *pText, const CUIRect *pRect);
|
||||
int DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, const CUIRect *pRect, int Corners=CUI::CORNER_ALL, float r=5.0f, bool Fade=true);
|
||||
int DoButton_SpriteID(CButtonContainer *pBC, int ImageID, int SpriteID, bool Checked, const CUIRect *pRect, int Corners=CUI::CORNER_ALL, float r=5.0f, bool Fade=true);
|
||||
int DoButton_SpriteClean(int ImageID, int SpriteID, const CUIRect *pRect);
|
||||
int DoButton_SpriteCleanID(const void *pID, int ImageID, int SpriteID, const CUIRect *pRect, bool Blend=true);
|
||||
int DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active);
|
||||
int DoButton_Menu(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName=0, int Corners=CUI::CORNER_ALL, float r=5.0f, float FontFactor=0.0f, vec4 ColorHot=vec4(1.0f, 1.0f, 1.0f, 0.75f), bool TextFade=true);
|
||||
int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners);
|
||||
int DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, int Corners=CUI::CORNER_ALL, float r=5.0f, float FontFactor=0.0f);
|
||||
int DoButton_MenuTabTop(CButtonContainer *pBC, const char *pText, int Checked, const CUIRect *pRect, float Alpha=1.0f, float FontAlpha=1.0f, int Corners=CUI::CORNER_ALL, float r=5.0f, float FontFactor=0.0f);
|
||||
void DoButton_MenuTabTop_Dummy(const char *pText, int Checked, const CUIRect *pRect, float Alpha);
|
||||
int DoButton_Customize(CButtonContainer *pBC, IGraphics::CTextureHandle Texture, int SpriteID, const CUIRect *pRect, float ImageRatio);
|
||||
|
||||
int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect, bool Checked=false);
|
||||
|
@ -84,6 +85,7 @@ private:
|
|||
void DoEditBoxOption(void *pID, char *pOption, int OptionLength, const CUIRect *pRect, const char *pStr, float VSplitVal, float *pOffset, bool Hidden=false);
|
||||
void DoScrollbarOption(void *pID, int *pOption, const CUIRect *pRect, const char *pStr, float VSplitVal, int Min, int Max, bool infinite=false);
|
||||
float DoDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback);
|
||||
float DoIndependentDropdownMenu(void *pID, const CUIRect *pRect, const char *pStr, float HeaderHeight, FDropdownCallback pfnCallback, bool* pActive);
|
||||
void DoInfoBox(const CUIRect *pRect, const char *pLable, const char *pValue);
|
||||
//static int ui_do_edit_box(void *id, const CUIRect *rect, char *str, unsigned str_size, float font_size, bool hidden=false);
|
||||
|
||||
|
@ -162,35 +164,35 @@ private:
|
|||
PAGE_CALLVOTE,
|
||||
PAGE_INTERNET,
|
||||
PAGE_LAN,
|
||||
PAGE_FRIENDS,
|
||||
PAGE_DEMOS,
|
||||
PAGE_SETTINGS,
|
||||
PAGE_SYSTEM,
|
||||
PAGE_START,
|
||||
|
||||
PAGE_BROWSER_BROWSER=0,
|
||||
PAGE_BROWSER_FRIENDS,
|
||||
NUM_PAGE_BROWSER,
|
||||
|
||||
SETTINGS_GENERAL=0,
|
||||
SETTINGS_PLAYER,
|
||||
SETTINGS_TEE,
|
||||
SETTINGS_CONTROLS,
|
||||
SETTINGS_GRAPHICS,
|
||||
SETTINGS_SOUND,
|
||||
|
||||
ACTLB_LANG=0,
|
||||
ACTLB_THEME,
|
||||
};
|
||||
|
||||
int m_GamePage;
|
||||
int m_Popup;
|
||||
int m_ActivePage;
|
||||
int m_MenuPage;
|
||||
int m_BorwserPage;
|
||||
bool m_MenuActive;
|
||||
int m_SidebarTab;
|
||||
bool m_SidebarActive;
|
||||
bool m_ShowServerDetails;
|
||||
bool m_UseMouseButtons;
|
||||
vec2 m_MousePos;
|
||||
vec2 m_PrevMousePos;
|
||||
bool m_InfoMode;
|
||||
bool m_PopupActive;
|
||||
int m_ActiveListBox;
|
||||
|
||||
// images
|
||||
struct CMenuImage
|
||||
|
@ -205,6 +207,24 @@ private:
|
|||
|
||||
const CMenuImage *FindMenuImage(const char* pName);
|
||||
|
||||
// themes
|
||||
class CTheme
|
||||
{
|
||||
public:
|
||||
CTheme() {}
|
||||
CTheme(const char *n, bool HasDay, bool HasNight) : m_Name(n), m_HasDay(HasDay), m_HasNight(HasNight) {}
|
||||
|
||||
string m_Name;
|
||||
bool m_HasDay;
|
||||
bool m_HasNight;
|
||||
IGraphics::CTextureHandle m_IconTexture;
|
||||
bool operator<(const CTheme &Other) { return m_Name < Other.m_Name; }
|
||||
};
|
||||
sorted_array<CTheme> m_lThemes;
|
||||
|
||||
static int ThemeScan(const char *pName, int IsDir, int DirType, void *pUser);
|
||||
static int ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser);
|
||||
|
||||
int64 m_LastInput;
|
||||
|
||||
// loading
|
||||
|
@ -223,6 +243,7 @@ private:
|
|||
static float ms_ButtonHeight;
|
||||
static float ms_ListheaderHeight;
|
||||
static float ms_FontmodHeight;
|
||||
static float ms_BackgroundAlpha;
|
||||
|
||||
// for settings
|
||||
bool m_NeedRestartGraphics;
|
||||
|
@ -237,7 +258,10 @@ private:
|
|||
//
|
||||
bool m_EscapePressed;
|
||||
bool m_EnterPressed;
|
||||
bool m_TabPressed;
|
||||
bool m_DeletePressed;
|
||||
bool m_UpArrowPressed;
|
||||
bool m_DownArrowPressed;
|
||||
|
||||
// for map download popup
|
||||
int64 m_DownloadLastCheckTime;
|
||||
|
@ -286,30 +310,11 @@ private:
|
|||
class CFriendItem
|
||||
{
|
||||
public:
|
||||
class CClanFriendItem
|
||||
{
|
||||
public:
|
||||
CClanFriendItem()
|
||||
{
|
||||
m_lFriendInfos.clear();
|
||||
m_lServerInfos.clear();
|
||||
}
|
||||
|
||||
~CClanFriendItem()
|
||||
{
|
||||
m_lFriendInfos.clear();
|
||||
m_lServerInfos.clear();
|
||||
}
|
||||
|
||||
array<CFriendInfo> m_lFriendInfos;
|
||||
array<const CServerInfo*> m_lServerInfos;
|
||||
};
|
||||
|
||||
int m_NumFound;
|
||||
const CFriendInfo *m_pFriendInfo;
|
||||
const CServerInfo *m_pServerInfo;
|
||||
|
||||
CClanFriendItem m_ClanFriend;
|
||||
char m_aName[MAX_NAME_LENGTH];
|
||||
char m_aClan[MAX_CLAN_LENGTH];
|
||||
bool m_IsPlayer;
|
||||
|
||||
CFriendItem()
|
||||
{
|
||||
|
@ -317,48 +322,31 @@ private:
|
|||
m_pServerInfo = 0;
|
||||
}
|
||||
|
||||
bool IsClanFriend()
|
||||
bool operator<(const CFriendItem &Other)
|
||||
{
|
||||
return m_pFriendInfo->m_aClan[0] && !m_pFriendInfo->m_aName[0];
|
||||
if(m_aName[0] && !Other.m_aName[0])
|
||||
return true;
|
||||
if(!m_aName[0] && Other.m_aName[0])
|
||||
return false;
|
||||
int Result = str_comp_nocase(m_aName, Other.m_aName);
|
||||
if(Result < 0 || (Result == 0 && str_comp_nocase(m_aClan, Other.m_aClan) < 0))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_NumFound = 0;
|
||||
m_ClanFriend.m_lFriendInfos.clear();
|
||||
m_ClanFriend.m_lServerInfos.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct CSelectedFriend
|
||||
{
|
||||
bool m_ClanFriend;
|
||||
bool m_FakeFriend;
|
||||
unsigned m_NameHash;
|
||||
unsigned m_ClanHash;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FRIENDS_SORT_TYPE = 0,
|
||||
FRIENDS_SORT_SERVER,
|
||||
FRIENDS_SORT_NAME,
|
||||
FRIENDS_SORT_CLAN,
|
||||
FRIEND_PLAYER_ON = 0,
|
||||
FRIEND_CLAN_ON,
|
||||
FRIEND_OFF,
|
||||
NUM_FRIEND_TYPES
|
||||
};
|
||||
|
||||
int *m_pFriendIndexes;
|
||||
array<CFriendItem> m_lFriends;
|
||||
int m_FriendlistSelectedIndex;
|
||||
const CFriendInfo *m_pDeleteFriendInfo;
|
||||
CSelectedFriend m_SelectedFriend;
|
||||
|
||||
bool SortCompareName(int Index1, int Index2) const;
|
||||
bool SortCompareClan(int Index1, int Index2) const;
|
||||
bool SortCompareServer(int Index1, int Index2) const;
|
||||
bool SortCompareType(int Index1, int Index2) const;
|
||||
sorted_array<CFriendItem> m_lFriendList[NUM_FRIEND_TYPES];
|
||||
const CFriendItem *m_pDeleteFriend;
|
||||
|
||||
void FriendlistOnUpdate();
|
||||
void SortFriends();
|
||||
|
||||
class CBrowserFilter
|
||||
{
|
||||
|
@ -368,6 +356,10 @@ private:
|
|||
int m_Filter;
|
||||
class IServerBrowser *m_pServerBrowser;
|
||||
|
||||
static class CServerFilterInfo ms_FilterStandard;
|
||||
static class CServerFilterInfo ms_FilterFavorites;
|
||||
static class CServerFilterInfo ms_FilterAll;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
|
@ -379,9 +371,10 @@ private:
|
|||
};
|
||||
// buttons var
|
||||
int m_SwitchButton;
|
||||
int m_aButtonID[3];
|
||||
|
||||
CBrowserFilter() {}
|
||||
CBrowserFilter(int Custom, const char* pName, IServerBrowser *pServerBrowser, int Filter, int Ping, int Country, const char* pGametype, const char* pServerAddress);
|
||||
CBrowserFilter(int Custom, const char* pName, IServerBrowser *pServerBrowser);
|
||||
void Switch();
|
||||
bool Extended() const;
|
||||
int Custom() const;
|
||||
|
@ -395,6 +388,7 @@ private:
|
|||
const CServerInfo *SortedGet(int Index) const;
|
||||
const void *ID(int Index) const;
|
||||
|
||||
void Reset();
|
||||
void GetFilter(class CServerFilterInfo *pFilterInfo) const;
|
||||
void SetFilter(const class CServerFilterInfo *pFilterInfo);
|
||||
};
|
||||
|
@ -448,16 +442,7 @@ private:
|
|||
COL_BROWSER_MAP,
|
||||
COL_BROWSER_PLAYERS,
|
||||
COL_BROWSER_PING,
|
||||
COL_BROWSER_FAVORITE,
|
||||
COL_BROWSER_INFO,
|
||||
NUM_BROWSER_COLS,
|
||||
|
||||
COL_FRIEND_TYPE = 0,
|
||||
COL_FRIEND_SERVER,
|
||||
COL_FRIEND_NAME,
|
||||
COL_FRIEND_CLAN,
|
||||
COL_FRIEND_DELETE,
|
||||
NUM_FRIEND_COLS,
|
||||
};
|
||||
|
||||
struct CColumn
|
||||
|
@ -473,7 +458,6 @@ private:
|
|||
};
|
||||
|
||||
static CColumn ms_aBrowserCols[NUM_BROWSER_COLS];
|
||||
static CColumn ms_aFriendCols[NUM_FRIEND_COLS];
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -524,15 +508,21 @@ private:
|
|||
void RenderServerControlServer(CUIRect MainView);
|
||||
|
||||
// found in menus_browser.cpp
|
||||
int m_ScrollOffset;
|
||||
// int m_ScrollOffset;
|
||||
void RenderServerbrowserServerList(CUIRect View);
|
||||
void RenderServerbrowserSidebar(CUIRect View);
|
||||
void RenderServerbrowserFriendTab(CUIRect View);
|
||||
void RenderServerbrowserFilterTab(CUIRect View);
|
||||
void RenderServerbrowserInfoTab(CUIRect View);
|
||||
void RenderServerbrowserFriendList(CUIRect View);
|
||||
void RenderDetailInfo(CUIRect View, const CServerInfo *pInfo);
|
||||
void RenderDetailScoreboard(CUIRect View, const CServerInfo *pInfo, int Column);
|
||||
void RenderServerbrowserServerDetail(CUIRect View, const CServerInfo *pInfo);
|
||||
//void RenderServerbrowserFriends(CUIRect View);
|
||||
void RenderServerbrowserBottomBox(CUIRect View);
|
||||
void RenderServerbrowserOverlay();
|
||||
bool RenderFilterHeader(CUIRect View, int FilterIndex);
|
||||
int DoBrowserEntry(const void *pID, CUIRect *pRect, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected);
|
||||
int DoBrowserEntry(const void *pID, CUIRect View, const CServerInfo *pEntry, const CBrowserFilter *pFilter, bool Selected);
|
||||
void RenderServerbrowser(CUIRect MainView);
|
||||
static void ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
static void ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
|
||||
|
@ -544,6 +534,7 @@ private:
|
|||
|
||||
// found in menus_settings.cpp
|
||||
void RenderLanguageSelection(CUIRect MainView, bool Header=true);
|
||||
void RenderThemeSelection(CUIRect MainView, bool Header=true);
|
||||
void RenderHSLPicker(CUIRect Picker);
|
||||
void RenderSkinSelection(CUIRect MainView);
|
||||
void RenderSkinPartSelection(CUIRect MainView);
|
||||
|
@ -572,8 +563,6 @@ private:
|
|||
void InvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CMenus *pMenu, CUIRect Rect), void *pExtra=0);
|
||||
void DoPopupMenu();
|
||||
|
||||
static int PopupFilter(CMenus *pMenus, CUIRect View);
|
||||
|
||||
IGraphics::CTextureHandle m_TextureBlob;
|
||||
|
||||
void ToggleMusic();
|
||||
|
|
|
@ -181,12 +181,12 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
|
|||
static CButtonContainer s_PlayPauseButton;
|
||||
if(!pInfo->m_Paused)
|
||||
{
|
||||
if(DoButton_SpriteID(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PAUSE, &Button, CUI::CORNER_ALL))
|
||||
if(DoButton_SpriteID(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PAUSE, false, &Button, CUI::CORNER_ALL))
|
||||
DemoPlayer()->Pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DoButton_SpriteID(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PLAY, &Button, CUI::CORNER_ALL))
|
||||
if(DoButton_SpriteID(&s_PlayPauseButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_PLAY, false, &Button, CUI::CORNER_ALL))
|
||||
DemoPlayer()->Unpause();
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
|
|||
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
||||
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
||||
static CButtonContainer s_ResetButton;
|
||||
if(DoButton_SpriteID(&s_ResetButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_STOP, &Button, CUI::CORNER_ALL))
|
||||
if(DoButton_SpriteID(&s_ResetButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_STOP, false, &Button, CUI::CORNER_ALL))
|
||||
{
|
||||
m_pClient->OnReset();
|
||||
DemoPlayer()->Pause();
|
||||
|
@ -206,14 +206,14 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
|
|||
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
||||
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
||||
static CButtonContainer s_SlowDownButton;
|
||||
if(DoButton_SpriteID(&s_SlowDownButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_SLOWER, &Button, CUI::CORNER_ALL))
|
||||
if(DoButton_SpriteID(&s_SlowDownButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_SLOWER, false, &Button, CUI::CORNER_ALL))
|
||||
DecreaseDemoSpeed = true;
|
||||
|
||||
// fastforward
|
||||
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
|
||||
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
|
||||
static CButtonContainer s_FastForwardButton;
|
||||
if(DoButton_SpriteID(&s_FastForwardButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_FASTER, &Button, CUI::CORNER_ALL))
|
||||
if(DoButton_SpriteID(&s_FastForwardButton, IMAGE_DEMOBUTTONS, SPRITE_DEMOBUTTON_FASTER, false, &Button, CUI::CORNER_ALL))
|
||||
IncreaseDemoSpeed = true;
|
||||
|
||||
// speed meter
|
||||
|
@ -320,6 +320,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
|
|||
|
||||
// cut view
|
||||
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), CUI::CORNER_ALL, 5.0f);
|
||||
BottomView.HSplitTop(20.f, 0, &BottomView);
|
||||
|
||||
static int s_Inited = 0;
|
||||
|
|
|
@ -81,8 +81,9 @@ void CMenus::RenderGame(CUIRect MainView)
|
|||
{
|
||||
// print notice
|
||||
CUIRect Bar;
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitTop(45.0f, &Bar, &MainView);
|
||||
RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 10.0f);
|
||||
RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f+ms_BackgroundAlpha), CUI::CORNER_ALL, 5.0f);
|
||||
Bar.HMargin(15.0f, &Bar);
|
||||
UI()->DoLabelScaled(&Bar, Info.m_aNotification, 14.0f, CUI::ALIGN_CENTER);
|
||||
}
|
||||
|
@ -191,37 +192,43 @@ void CMenus::RenderGame(CUIRect MainView)
|
|||
|
||||
void CMenus::RenderPlayers(CUIRect MainView)
|
||||
{
|
||||
CUIRect Button, ButtonBar, Options, Player;
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
const float ButtonHeight = 20.0f;
|
||||
const float Spacing = 2.0f;
|
||||
const float NameWidth = 250.0f;
|
||||
const float ClanWidth = 250.0f;
|
||||
CUIRect Label, Row;
|
||||
MainView.HSplitBottom(80.0f, &MainView, 0);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f+ms_BackgroundAlpha), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
// player options
|
||||
MainView.Margin(10.0f, &Options);
|
||||
RenderTools()->DrawUIRect(&Options, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
Options.Margin(10.0f, &Options);
|
||||
Options.HSplitTop(50.0f, &Button, &Options);
|
||||
UI()->DoLabelScaled(&Button, Localize("Player options"), 34.0f, CUI::ALIGN_LEFT);
|
||||
MainView.HSplitTop(ButtonHeight, &Label, &MainView);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, Localize("Player options"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
MainView.Margin(5.0f, &MainView);
|
||||
|
||||
// headline
|
||||
Options.HSplitTop(34.0f, &ButtonBar, &Options);
|
||||
ButtonBar.VSplitRight(220.0f, &Player, &ButtonBar);
|
||||
UI()->DoLabelScaled(&Player, Localize("Player"), 24.0f, CUI::ALIGN_LEFT);
|
||||
MainView.HSplitTop(ButtonHeight, &Row, &MainView);
|
||||
Row.VSplitLeft(ButtonHeight+Spacing, 0, &Row);
|
||||
Row.VSplitLeft(NameWidth, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, Localize("Player"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
ButtonBar.HMargin(1.0f, &ButtonBar);
|
||||
float Width = ButtonBar.h*2.0f;
|
||||
ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
|
||||
Row.VSplitRight(2*ButtonHeight, &Row, &Label);
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GUIICONS].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
RenderTools()->SelectSprite(SPRITE_GUIICON_MUTE);
|
||||
IGraphics::CQuadItem QuadItem(Button.x, Button.y, Button.w, Button.h);
|
||||
IGraphics::CQuadItem QuadItem(Label.x, Label.y, Label.w, Label.h);
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
|
||||
ButtonBar.VSplitLeft(20.0f, 0, &ButtonBar);
|
||||
ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
|
||||
Row.VSplitRight(2*Spacing, &Row, 0);
|
||||
Row.VSplitRight(2*ButtonHeight, &Row, &Label);
|
||||
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GUIICONS].m_Id);
|
||||
Graphics()->QuadsBegin();
|
||||
RenderTools()->SelectSprite(SPRITE_GUIICON_FRIEND);
|
||||
QuadItem = IGraphics::CQuadItem(Button.x, Button.y, Button.w, Button.h);
|
||||
QuadItem = IGraphics::CQuadItem(Label.x, Label.y, Label.w, Label.h);
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
|
||||
|
@ -235,47 +242,49 @@ void CMenus::RenderPlayers(CUIRect MainView)
|
|||
if(i == m_pClient->m_LocalClientID || !m_pClient->m_aClients[i].m_Active || m_pClient->m_aClients[i].m_Team != Teams[Team])
|
||||
continue;
|
||||
|
||||
Options.HSplitTop(28.0f, &ButtonBar, &Options);
|
||||
if(Count++%2 == 0)
|
||||
RenderTools()->DrawUIRect(&ButtonBar, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
ButtonBar.VSplitRight(220.0f, &Player, &ButtonBar);
|
||||
MainView.HSplitTop(ButtonHeight, &Row, &MainView);
|
||||
if(Count++ % 2 == 0)
|
||||
RenderTools()->DrawUIRect(&Row, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
// player info
|
||||
Player.VSplitLeft(28.0f, &Button, &Player);
|
||||
Row.VSplitLeft(ButtonHeight, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
CTeeRenderInfo Info = m_pClient->m_aClients[i].m_RenderInfo;
|
||||
Info.m_Size = Button.h;
|
||||
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Button.x+Button.h/2, Button.y+Button.h/2));
|
||||
Info.m_Size = Label.h;
|
||||
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Label.x + Label.h / 2, Label.y + Label.h / 2));
|
||||
|
||||
Player.HSplitTop(1.5f, 0, &Player);
|
||||
Player.VSplitMid(&Player, &Button);
|
||||
CTextCursor Cursor;
|
||||
TextRender()->SetCursor(&Cursor, Player.x, Player.y, 14.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
||||
Cursor.m_LineWidth = Player.w;
|
||||
Row.VSplitLeft(2*Spacing, 0, &Row);
|
||||
Row.VSplitLeft(NameWidth, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
if(g_Config.m_ClShowUserId)
|
||||
{
|
||||
CTextCursor Cursor;
|
||||
TextRender()->SetCursor(&Cursor, Label.x, Label.y, ButtonHeight*ms_FontmodHeight*0.8f, TEXTFLAG_RENDER);
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, i);
|
||||
Label.VSplitLeft(ButtonHeight, 0, &Label);
|
||||
}
|
||||
char aBuf[64];
|
||||
str_format(aBuf, sizeof(aBuf), "%2d: %s", i, g_Config.m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : "");
|
||||
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||
|
||||
TextRender()->SetCursor(&Cursor, Button.x,Button.y, 14.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
||||
Cursor.m_LineWidth = Button.w;
|
||||
TextRender()->TextEx(&Cursor, m_pClient->m_aClients[i].m_aClan, -1);
|
||||
str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[i].m_aName : "");
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
Row.VSplitLeft(Spacing, 0, &Row);
|
||||
Row.VSplitLeft(ClanWidth, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[i].m_aClan : "");
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
// ignore button
|
||||
ButtonBar.HMargin(2.0f, &ButtonBar);
|
||||
ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
|
||||
Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button);
|
||||
Button.VSplitLeft(Button.h, &Button, 0);
|
||||
Row.VSplitRight(ButtonHeight/2, &Row, 0);
|
||||
Row.VSplitRight(ButtonHeight, &Row, &Label);
|
||||
if(g_Config.m_ClFilterchat == 2 || (g_Config.m_ClFilterchat == 1 && !m_pClient->m_aClients[i].m_Friend))
|
||||
DoButton_Toggle(&s_aPlayerIDs[i][0], 1, &Button, false);
|
||||
DoButton_Toggle(&s_aPlayerIDs[i][0], 1, &Label, false);
|
||||
else
|
||||
if(DoButton_Toggle(&s_aPlayerIDs[i][0], m_pClient->m_aClients[i].m_ChatIgnore, &Button, true))
|
||||
if(DoButton_Toggle(&s_aPlayerIDs[i][0], m_pClient->m_aClients[i].m_ChatIgnore, &Label, true))
|
||||
m_pClient->m_aClients[i].m_ChatIgnore ^= 1;
|
||||
|
||||
// friend button
|
||||
ButtonBar.VSplitLeft(20.0f, &Button, &ButtonBar);
|
||||
ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
|
||||
Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button);
|
||||
Button.VSplitLeft(Button.h, &Button, 0);
|
||||
if(DoButton_Toggle(&s_aPlayerIDs[i][1], m_pClient->m_aClients[i].m_Friend, &Button, true))
|
||||
Row.VSplitRight(2*Spacing+ButtonHeight,&Row, 0);
|
||||
Row.VSplitRight(ButtonHeight, &Row, &Label);
|
||||
if(DoButton_Toggle(&s_aPlayerIDs[i][1], m_pClient->m_aClients[i].m_Friend, &Label, true))
|
||||
{
|
||||
if(m_pClient->m_aClients[i].m_Friend)
|
||||
m_pClient->Friends()->RemoveFriend(m_pClient->m_aClients[i].m_aName, m_pClient->m_aClients[i].m_aClan);
|
||||
|
@ -298,103 +307,108 @@ void CMenus::RenderServerInfo(CUIRect MainView)
|
|||
Client()->GetServerInfo(&CurrentServerInfo);
|
||||
|
||||
// render background
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
MainView.HSplitBottom(80.0f, &MainView, 0);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
CUIRect View, ServerInfo, GameInfo, Motd;
|
||||
CUIRect ServerInfo, GameInfo, Motd, Label;
|
||||
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
char aBuf[1024];
|
||||
|
||||
// set view to use for all sub-modules
|
||||
MainView.Margin(10.0f, &View);
|
||||
char aBuf[128] = {0};
|
||||
const float ButtonHeight = 20.0f;
|
||||
|
||||
// serverinfo
|
||||
View.HSplitTop(View.h/2/UI()->Scale()-5.0f, &ServerInfo, &Motd);
|
||||
ServerInfo.VSplitLeft(View.w/2/UI()->Scale()-5.0f, &ServerInfo, &GameInfo);
|
||||
RenderTools()->DrawUIRect(&ServerInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
MainView.HSplitBottom(250.0f, &ServerInfo, &Motd);
|
||||
ServerInfo.VSplitMid(&ServerInfo, &GameInfo);
|
||||
ServerInfo.VSplitRight(1.0f, &ServerInfo, 0);
|
||||
RenderTools()->DrawUIRect(&ServerInfo, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, Localize("Server info"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
RenderTools()->DrawUIRect(&ServerInfo, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
ServerInfo.Margin(5.0f, &ServerInfo);
|
||||
|
||||
ServerInfo.HSplitTop(2*ButtonHeight, &Label, &ServerInfo);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, CurrentServerInfo.m_aName, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
x = 5.0f;
|
||||
y = 0.0f;
|
||||
ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Address"), g_Config.m_UiServerAddress);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Ping"), m_pClient->m_Snap.m_pLocalInfo->m_Latency);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 32, Localize("Server info"), 250);
|
||||
y += 32.0f+5.0f;
|
||||
|
||||
mem_zero(aBuf, sizeof(aBuf));
|
||||
str_format(
|
||||
aBuf,
|
||||
sizeof(aBuf),
|
||||
"%s\n\n"
|
||||
"%s: %s\n"
|
||||
"%s: %d\n"
|
||||
"%s: %s\n"
|
||||
"%s: %s\n",
|
||||
CurrentServerInfo.m_aName,
|
||||
Localize("Address"), g_Config.m_UiServerAddress,
|
||||
Localize("Ping"), m_pClient->m_Snap.m_pLocalInfo->m_Latency,
|
||||
Localize("Version"), CurrentServerInfo.m_aVersion,
|
||||
Localize("Password"), CurrentServerInfo.m_Flags&IServerBrowser::FLAG_PASSWORD ? Localize("Yes") : Localize("No")
|
||||
);
|
||||
|
||||
TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 20, aBuf, 250);
|
||||
ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Version"), CurrentServerInfo.m_aVersion);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
ServerInfo.HSplitTop(ButtonHeight, &Label, &ServerInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Password"), CurrentServerInfo.m_Flags&IServerBrowser::FLAG_PASSWORD ? Localize("Yes", "With") : Localize("No", "Without/None"));
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
const bool IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr);
|
||||
ServerInfo.HSplitBottom(ButtonHeight, &ServerInfo, &Label);
|
||||
static int s_AddFavButton = 0;
|
||||
if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite, &Label))
|
||||
{
|
||||
CUIRect Button;
|
||||
bool IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr);
|
||||
ServerInfo.HSplitBottom(20.0f, &ServerInfo, &Button);
|
||||
static int s_AddFavButton = 0;
|
||||
if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite, &Button))
|
||||
{
|
||||
if(IsFavorite)
|
||||
ServerBrowser()->RemoveFavorite(&CurrentServerInfo);
|
||||
if(IsFavorite)
|
||||
ServerBrowser()->RemoveFavorite(&CurrentServerInfo);
|
||||
else
|
||||
ServerBrowser()->AddFavorite(&CurrentServerInfo);
|
||||
}
|
||||
ServerBrowser()->AddFavorite(&CurrentServerInfo);
|
||||
}
|
||||
|
||||
// gameinfo
|
||||
GameInfo.VSplitLeft(10.0f, 0x0, &GameInfo);
|
||||
RenderTools()->DrawUIRect(&GameInfo, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
GameInfo.VSplitLeft(1.0f, 0, &GameInfo);
|
||||
RenderTools()->DrawUIRect(&GameInfo, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
GameInfo.HSplitTop(ButtonHeight, &Label, &GameInfo);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, Localize("Game info"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
RenderTools()->DrawUIRect(&GameInfo, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
GameInfo.Margin(5.0f, &GameInfo);
|
||||
|
||||
x = 5.0f;
|
||||
y = 0.0f;
|
||||
GameInfo.HSplitTop(ButtonHeight, &Label, &GameInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Game type"), CurrentServerInfo.m_aGameType);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 32, Localize("Game info"), 250);
|
||||
y += 32.0f+5.0f;
|
||||
GameInfo.HSplitTop(ButtonHeight, &Label, &GameInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Map"), CurrentServerInfo.m_aMap);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
mem_zero(aBuf, sizeof(aBuf));
|
||||
str_format(
|
||||
aBuf,
|
||||
sizeof(aBuf),
|
||||
"\n\n"
|
||||
"%s: %s\n"
|
||||
"%s: %s\n"
|
||||
"%s: %d\n"
|
||||
"%s: %d\n"
|
||||
"\n"
|
||||
"%s: %d/%d\n",
|
||||
Localize("Game type"), CurrentServerInfo.m_aGameType,
|
||||
Localize("Map"), CurrentServerInfo.m_aMap,
|
||||
Localize("Score limit"), m_pClient->m_GameInfo.m_ScoreLimit,
|
||||
Localize("Time limit"), m_pClient->m_GameInfo.m_TimeLimit,
|
||||
Localize("Players"), m_pClient->m_GameInfo.m_NumPlayers, CurrentServerInfo.m_MaxClients
|
||||
);
|
||||
TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 20, aBuf, 250);
|
||||
GameInfo.HSplitTop(ButtonHeight, &Label, &GameInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Score limit"), m_pClient->m_GameInfo.m_ScoreLimit);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
GameInfo.HSplitTop(ButtonHeight, &Label, &GameInfo);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Time limit"), m_pClient->m_GameInfo.m_TimeLimit);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
GameInfo.HSplitBottom(ButtonHeight, &GameInfo, &Label);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s: %d/%d", Localize("Players"), m_pClient->m_GameInfo.m_NumPlayers, CurrentServerInfo.m_MaxClients);
|
||||
UI()->DoLabel(&Label, aBuf, ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
// motd
|
||||
Motd.HSplitTop(10.0f, 0, &Motd);
|
||||
RenderTools()->DrawUIRect(&Motd, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
Motd.HSplitTop(2.0f, 0, &Motd);
|
||||
RenderTools()->DrawUIRect(&Motd, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
Motd.HSplitTop(ButtonHeight, &Label, &Motd);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, Localize("MOTD"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
RenderTools()->DrawUIRect(&Motd, vec4(0.0, 0.0, 0.0, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
Motd.Margin(5.0f, &Motd);
|
||||
y = 0.0f;
|
||||
x = 5.0f;
|
||||
TextRender()->Text(0, Motd.x+x, Motd.y+y, 32, Localize("MOTD"), -1);
|
||||
y += 32.0f+5.0f;
|
||||
TextRender()->Text(0, Motd.x+x, Motd.y+y, 16, m_pClient->m_pMotd->m_aServerMotd, (int)Motd.w);
|
||||
|
||||
TextRender()->Text(0, Motd.x, Motd.y, ButtonHeight*ms_FontmodHeight*0.8f, m_pClient->m_pMotd->m_aServerMotd, (int)Motd.w);
|
||||
}
|
||||
|
||||
void CMenus::RenderServerControlServer(CUIRect MainView)
|
||||
|
@ -402,15 +416,19 @@ void CMenus::RenderServerControlServer(CUIRect MainView)
|
|||
static int s_VoteList = 0;
|
||||
static CListBoxState s_ListBoxState;
|
||||
CUIRect List = MainView;
|
||||
UiDoListboxHeader(&s_ListBoxState, &List, "", 20.0f, 2.0f);
|
||||
UiDoListboxStart(&s_ListBoxState, &s_VoteList, 24.0f, "", m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption);
|
||||
UiDoListboxHeader(&s_ListBoxState, &List, Localize("Option"), 20.0f, 2.0f);
|
||||
UiDoListboxStart(&s_ListBoxState, &s_VoteList, 20.0f, 0, m_pClient->m_pVoting->m_NumVoteOptions, 1, m_CallvoteSelectedOption, 0, true);
|
||||
|
||||
for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext)
|
||||
{
|
||||
CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, pOption);
|
||||
|
||||
if(Item.m_Visible)
|
||||
UI()->DoLabelScaled(&Item.m_Rect, pOption->m_aDescription, 16.0f, CUI::ALIGN_LEFT);
|
||||
{
|
||||
Item.m_Rect.VMargin(5.0f, &Item.m_Rect);
|
||||
Item.m_Rect.y += 2.0f;
|
||||
UI()->DoLabel(&Item.m_Rect, pOption->m_aDescription, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
m_CallvoteSelectedOption = UiDoListboxEnd(&s_ListBoxState, 0);
|
||||
|
@ -428,7 +446,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
|
|||
{
|
||||
if(i == m_pClient->m_LocalClientID || !m_pClient->m_aClients[i].m_Active || m_pClient->m_aClients[i].m_Team != Teams[Team] ||
|
||||
(FilterSpectators && m_pClient->m_aClients[i].m_Team == TEAM_SPECTATORS) ||
|
||||
(!FilterSpectators && m_pClient->m_Snap.m_paPlayerInfos[i] && m_pClient->m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_ADMIN))
|
||||
(!FilterSpectators && m_pClient->m_Snap.m_paPlayerInfos[i] && (m_pClient->m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_ADMIN)))
|
||||
continue;
|
||||
if(m_CallvoteSelectedPlayer == i)
|
||||
Selected = NumOptions;
|
||||
|
@ -436,11 +454,14 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
|
|||
}
|
||||
}
|
||||
|
||||
const float Spacing = 2.0f;
|
||||
const float NameWidth = 250.0f;
|
||||
const float ClanWidth = 250.0f;
|
||||
static int s_VoteList = 0;
|
||||
static CListBoxState s_ListBoxState;
|
||||
CUIRect List = MainView;
|
||||
UiDoListboxHeader(&s_ListBoxState, &List, "", 20.0f, 2.0f);
|
||||
UiDoListboxStart(&s_ListBoxState, &s_VoteList, 24.0f, "", NumOptions, 1, Selected);
|
||||
UiDoListboxHeader(&s_ListBoxState, &List, Localize("Player"), 20.0f, 2.0f);
|
||||
UiDoListboxStart(&s_ListBoxState, &s_VoteList, 20.0f, 0, NumOptions, 1, Selected, 0, true);
|
||||
|
||||
for(int i = 0; i < NumOptions; i++)
|
||||
{
|
||||
|
@ -448,14 +469,37 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
|
|||
|
||||
if(Item.m_Visible)
|
||||
{
|
||||
CUIRect Label, Row;
|
||||
Item.m_Rect.VMargin(5.0f, &Row);
|
||||
|
||||
// player info
|
||||
Row.VSplitLeft(Row.h, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
CTeeRenderInfo Info = m_pClient->m_aClients[aPlayerIDs[i]].m_RenderInfo;
|
||||
Info.m_Size = Item.m_Rect.h;
|
||||
Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top
|
||||
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), vec2(Item.m_Rect.x+Item.m_Rect.h/2, Item.m_Rect.y+Item.m_Rect.h/2));
|
||||
Item.m_Rect.x +=Info.m_Size;
|
||||
Info.m_Size = Label.h;
|
||||
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Label.x + Label.h / 2, Label.y + Label.h / 2));
|
||||
|
||||
Row.VSplitLeft(2*Spacing, 0, &Row);
|
||||
if(g_Config.m_ClShowUserId)
|
||||
{
|
||||
Row.VSplitLeft(Row.h, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
CTextCursor Cursor;
|
||||
TextRender()->SetCursor(&Cursor, Label.x, Label.y, Label.h*ms_FontmodHeight*0.8f, TEXTFLAG_RENDER);
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, aPlayerIDs[i]);
|
||||
}
|
||||
|
||||
Row.VSplitLeft(Spacing, 0, &Row);
|
||||
Row.VSplitLeft(NameWidth, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
char aBuf[64];
|
||||
str_format(aBuf, sizeof(aBuf), "%2d: %s", aPlayerIDs[i], g_Config.m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aName : "");
|
||||
UI()->DoLabelScaled(&Item.m_Rect, aBuf, 16.0f, CUI::ALIGN_LEFT);
|
||||
str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aName : "");
|
||||
UI()->DoLabel(&Label, aBuf, Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
Row.VSplitLeft(Spacing, 0, &Row);
|
||||
Row.VSplitLeft(ClanWidth, &Label, &Row);
|
||||
Label.y += 2.0f;
|
||||
str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[aPlayerIDs[i]].m_aClan : "");
|
||||
UI()->DoLabel(&Label, aBuf, Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,37 +551,40 @@ void CMenus::RenderServerControl(CUIRect MainView)
|
|||
}
|
||||
|
||||
bool Authed = Client()->RconAuthed();
|
||||
MainView.HSplitBottom(80.0f, &MainView, 0);
|
||||
if(pNotification && !Authed)
|
||||
{
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
// only print notice
|
||||
CUIRect Bar;
|
||||
MainView.HSplitTop(45.0f, &Bar, &MainView);
|
||||
RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
|
||||
RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f+ms_BackgroundAlpha), CUI::CORNER_ALL, 5.0f);
|
||||
Bar.HMargin(15.0f, &Bar);
|
||||
UI()->DoLabelScaled(&Bar, pNotification, 14.0f, CUI::ALIGN_CENTER);
|
||||
return;
|
||||
}
|
||||
|
||||
// tab bar
|
||||
CUIRect Bottom, Extended, TabBar, Button;
|
||||
MainView.HSplitTop(20.0f, &Bottom, &MainView);
|
||||
RenderTools()->DrawUIRect(&Bottom, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_T, 10.0f);
|
||||
MainView.HSplitTop(20.0f, &TabBar, &MainView);
|
||||
{
|
||||
TabBar.VSplitLeft(TabBar.w/3, &Button, &TabBar);
|
||||
static int s_Button0 = 0;
|
||||
if(DoButton_MenuTab(&s_Button0, Localize("Change settings"), s_ControlPage == 0, &Button, 0))
|
||||
s_ControlPage = 0;
|
||||
const float NotActiveAlpha = 0.5f;
|
||||
CUIRect Bottom, Extended, Button, Row, Note;
|
||||
MainView.HSplitTop(3.0f, 0, &MainView);
|
||||
MainView.HSplitTop(25.0f, &Row, &MainView);
|
||||
Row.VSplitLeft(Row.w/3-1.5f, &Button, &Row);
|
||||
static CButtonContainer s_Button0;
|
||||
if(DoButton_MenuTabTop(&s_Button0, Localize("Change settings"), false, &Button, s_ControlPage == 0 ? 1.0f : NotActiveAlpha, 1.0f, CUI::CORNER_T, 5.0f, 0.25f))
|
||||
s_ControlPage = 0;
|
||||
|
||||
TabBar.VSplitMid(&Button, &TabBar);
|
||||
static int s_Button1 = 0;
|
||||
if(DoButton_MenuTab(&s_Button1, Localize("Kick player"), s_ControlPage == 1, &Button, 0))
|
||||
s_ControlPage = 1;
|
||||
Row.VSplitLeft(1.5f, 0, &Row);
|
||||
Row.VSplitMid(&Button, &Row);
|
||||
Button.VMargin(1.5f, &Button);
|
||||
static CButtonContainer s_Button1;
|
||||
if(DoButton_MenuTabTop(&s_Button1, Localize("Kick player"), false, &Button, s_ControlPage == 1 ? 1.0f : NotActiveAlpha, 1.0f, CUI::CORNER_T, 5.0f, 0.25f))
|
||||
s_ControlPage = 1;
|
||||
|
||||
static int s_Button2 = 0;
|
||||
if(DoButton_MenuTab(&s_Button2, Localize("Move player to spectators"), s_ControlPage == 2, &TabBar, 0))
|
||||
s_ControlPage = 2;
|
||||
}
|
||||
Row.VSplitLeft(1.5f, 0, &Button);
|
||||
static CButtonContainer s_Button2;
|
||||
if(DoButton_MenuTabTop(&s_Button2, Localize("Move player to spectators"), false, &Button, s_ControlPage == 2 ? 1.0f : NotActiveAlpha, 1.0f, CUI::CORNER_T, 5.0f, 0.25f))
|
||||
s_ControlPage = 2;
|
||||
|
||||
if(s_ControlPage == 1)
|
||||
{
|
||||
|
@ -552,26 +599,26 @@ void CMenus::RenderServerControl(CUIRect MainView)
|
|||
else if(s_ControlPage == 2 && !m_pClient->m_ServerSettings.m_SpecVote)
|
||||
pNotification = Localize("Server does not allow voting to move players to spectators");
|
||||
|
||||
if(pNotification && !Authed)
|
||||
{
|
||||
MainView.HSplitTop(20.0f+45.0f, &MainView, 0);
|
||||
}
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), CUI::CORNER_B, 5.0f);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
if(pNotification && !Authed)
|
||||
{
|
||||
// only print notice
|
||||
CUIRect Bar;
|
||||
MainView.HSplitTop(45.0f, &Bar, &MainView);
|
||||
RenderTools()->DrawUIRect(&Bar, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 10.0f);
|
||||
Bar.HMargin(15.0f, &Bar);
|
||||
UI()->DoLabelScaled(&Bar, pNotification, 14.0f, CUI::ALIGN_CENTER);
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
MainView.HMargin(15.0f, &MainView);
|
||||
UI()->DoLabelScaled(&MainView, pNotification, 14.0f, CUI::ALIGN_CENTER);
|
||||
return;
|
||||
}
|
||||
|
||||
// render background
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_B, 10.0f);
|
||||
MainView.Margin(10.0f, &MainView);
|
||||
MainView.HSplitBottom(90.0f, &MainView, &Extended);
|
||||
|
||||
MainView.HSplitBottom(90.0f+2*20.0f, &MainView, &Extended);
|
||||
RenderTools()->DrawUIRect(&Extended, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
// render page
|
||||
MainView.HSplitBottom(ms_ButtonHeight + 5*2, &MainView, &Bottom);
|
||||
Bottom.HMargin(5.0f, &Bottom);
|
||||
|
||||
if(s_ControlPage == 0)
|
||||
RenderServerControlServer(MainView);
|
||||
else if(s_ControlPage == 1)
|
||||
|
@ -580,28 +627,33 @@ void CMenus::RenderServerControl(CUIRect MainView)
|
|||
RenderServerControlKick(MainView, true);
|
||||
|
||||
// vote menu
|
||||
Extended.Margin(5.0f, &Extended);
|
||||
Extended.HSplitTop(20.0f, &Note, &Extended);
|
||||
Extended.HSplitTop(20.0f, &Bottom, &Extended);
|
||||
{
|
||||
Bottom.VSplitRight(120.0f, &Bottom, &Button);
|
||||
|
||||
// render kick reason
|
||||
CUIRect Reason, ClearButton;
|
||||
CUIRect Reason, ClearButton, Label;
|
||||
Bottom.VSplitRight(40.0f, &Bottom, 0);
|
||||
Bottom.VSplitRight(160.0f, &Bottom, &Reason);
|
||||
Reason.HSplitTop(5.0f, 0, &Reason);
|
||||
Reason.VSplitRight(Reason.h, &Reason, &ClearButton);
|
||||
const char *pLabel = Localize("Reason:");
|
||||
UI()->DoLabelScaled(&Reason, pLabel, 14.0f, CUI::ALIGN_LEFT);
|
||||
float w = TextRender()->TextWidth(0, 14.0f, pLabel, -1);
|
||||
Reason.VSplitLeft(w+10.0f, 0, &Reason);
|
||||
float w = TextRender()->TextWidth(0, Reason.h*ms_FontmodHeight*0.8f, pLabel, -1);
|
||||
Reason.VSplitLeft(w + 10.0f, &Label, &Reason);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, pLabel, Reason.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
static float s_Offset = 0.0f;
|
||||
DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), 14.0f, &s_Offset, false, CUI::CORNER_L);
|
||||
DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), Reason.h*ms_FontmodHeight*0.8f, &s_Offset, false, CUI::CORNER_L);
|
||||
|
||||
// clear button
|
||||
{
|
||||
static CButtonContainer s_ClearButton;
|
||||
float Fade = ButtonFade(&s_ClearButton, 0.6f);
|
||||
RenderTools()->DrawUIRect(&ClearButton, vec4(1.0f, 1.0f, 1.0f, 0.33f+(Fade/0.6f)*0.165f), CUI::CORNER_R, 3.0f);
|
||||
UI()->DoLabel(&ClearButton, "x", ClearButton.h*ms_FontmodHeight, CUI::ALIGN_CENTER);
|
||||
Label = ClearButton;
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, "x", Label.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
if(UI()->DoButtonLogic(s_ClearButton.GetID(), "x", 0, &ClearButton))
|
||||
m_aCallvoteReason[0] = 0;
|
||||
}
|
||||
|
@ -616,7 +668,7 @@ void CMenus::RenderServerControl(CUIRect MainView)
|
|||
else
|
||||
{
|
||||
// print notice
|
||||
UI()->DoLabelScaled(&Bottom, pNotification, 14.0f, CUI::ALIGN_LEFT, Bottom.w);
|
||||
UI()->DoLabel(&Note, pNotification, Note.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT, Note.w);
|
||||
}
|
||||
|
||||
// extended features (only available when authed in rcon)
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include <engine/keys.h>
|
||||
#include <engine/storage.h>
|
||||
#include <engine/serverbrowser.h>
|
||||
#include <engine/textrender.h>
|
||||
|
||||
#include <generated/client_data.h>
|
||||
#include <generated/protocol.h>
|
||||
|
||||
#include "countryflags.h"
|
||||
#include "menus.h"
|
||||
|
@ -85,144 +89,3 @@ void CMenus::DoPopupMenu()
|
|||
}
|
||||
}
|
||||
|
||||
int CMenus::PopupFilter(CMenus *pMenus, CUIRect View)
|
||||
{
|
||||
CUIRect ServerFilter = View, FilterHeader;
|
||||
const float FontSize = 12.0f;
|
||||
|
||||
// slected filter
|
||||
CBrowserFilter *pFilter = &pMenus->m_lFilters[pMenus->m_SelectedFilter];
|
||||
CServerFilterInfo FilterInfo;
|
||||
pFilter->GetFilter(&FilterInfo);
|
||||
|
||||
// server filter
|
||||
ServerFilter.HSplitTop(ms_ListheaderHeight, &FilterHeader, &ServerFilter);
|
||||
pMenus->RenderTools()->DrawUIRect(&FilterHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
|
||||
pMenus->RenderTools()->DrawUIRect(&ServerFilter, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
|
||||
pMenus->UI()->DoLabelScaled(&FilterHeader, Localize("Server filter"), FontSize+2.0f, CUI::ALIGN_CENTER);
|
||||
CUIRect Button;
|
||||
|
||||
ServerFilter.VSplitLeft(5.0f, 0, &ServerFilter);
|
||||
ServerFilter.Margin(3.0f, &ServerFilter);
|
||||
ServerFilter.VMargin(5.0f, &ServerFilter);
|
||||
|
||||
int NewSortHash = FilterInfo.m_SortHash;
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterEmpty = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterEmpty, Localize("Has people playing"), FilterInfo.m_SortHash&IServerBrowser::FILTER_EMPTY, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_EMPTY;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterSpectators = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterSpectators, Localize("Count players only"), FilterInfo.m_SortHash&IServerBrowser::FILTER_SPECTATORS, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_SPECTATORS;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterFull = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterFull, Localize("Server not full"), FilterInfo.m_SortHash&IServerBrowser::FILTER_FULL, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_FULL;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterFriends = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterFriends, Localize("Show friends only"), FilterInfo.m_SortHash&IServerBrowser::FILTER_FRIENDS, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_FRIENDS;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterPw = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterPw, Localize("No password"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PW, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_PW;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterCompatversion = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterCompatversion, Localize("Compatible version"), FilterInfo.m_SortHash&IServerBrowser::FILTER_COMPAT_VERSION, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_COMPAT_VERSION;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterPure = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterPure, Localize("Standard gametype"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE, &Button) && pFilter->Custom() != CBrowserFilter::FILTER_STANDARD)
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_PURE;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterPureMap = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterPureMap, Localize("Standard map"), FilterInfo.m_SortHash&IServerBrowser::FILTER_PURE_MAP, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_PURE_MAP;
|
||||
|
||||
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
|
||||
static int s_BrFilterGametypeStrict = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterGametypeStrict, Localize("Strict gametype filter"), FilterInfo.m_SortHash&IServerBrowser::FILTER_GAMETYPE_STRICT, &Button))
|
||||
NewSortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_GAMETYPE_STRICT;
|
||||
|
||||
if(FilterInfo.m_SortHash != NewSortHash)
|
||||
{
|
||||
FilterInfo.m_SortHash = NewSortHash;
|
||||
pFilter->SetFilter(&FilterInfo);
|
||||
}
|
||||
|
||||
ServerFilter.HSplitTop(5.0f, 0, &ServerFilter);
|
||||
|
||||
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
|
||||
pMenus->UI()->DoLabelScaled(&Button, Localize("Game types:"), FontSize, CUI::ALIGN_LEFT);
|
||||
Button.VSplitRight(60.0f, 0, &Button);
|
||||
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
|
||||
static float Offset = 0.0f;
|
||||
static int s_BrFilterGametype = 0;
|
||||
if(pMenus->DoEditBox(&s_BrFilterGametype, &Button, FilterInfo.m_aGametype, sizeof(FilterInfo.m_aGametype), FontSize, &Offset))
|
||||
pFilter->SetFilter(&FilterInfo);
|
||||
|
||||
{
|
||||
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
|
||||
CUIRect EditBox;
|
||||
Button.VSplitRight(60.0f, &Button, &EditBox);
|
||||
|
||||
pMenus->UI()->DoLabelScaled(&Button, Localize("Maximum ping:"), FontSize, CUI::ALIGN_LEFT);
|
||||
|
||||
char aBuf[5];
|
||||
str_format(aBuf, sizeof(aBuf), "%d", FilterInfo.m_Ping);
|
||||
static float Offset = 0.0f;
|
||||
static int s_BrFilterPing = 0;
|
||||
pMenus->DoEditBox(&s_BrFilterPing, &EditBox, aBuf, sizeof(aBuf), FontSize, &Offset);
|
||||
int NewPing = clamp(str_toint(aBuf), 0, 999);
|
||||
if(NewPing != FilterInfo.m_Ping)
|
||||
{
|
||||
FilterInfo.m_Ping = NewPing;
|
||||
pFilter->SetFilter(&FilterInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// server address
|
||||
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
|
||||
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
|
||||
pMenus->UI()->DoLabelScaled(&Button, Localize("Server address:"), FontSize, CUI::ALIGN_LEFT);
|
||||
Button.VSplitRight(60.0f, 0, &Button);
|
||||
static float OffsetAddr = 0.0f;
|
||||
static int s_BrFilterServerAddress = 0;
|
||||
if(pMenus->DoEditBox(&s_BrFilterServerAddress, &Button, FilterInfo.m_aAddress, sizeof(FilterInfo.m_aAddress), FontSize, &OffsetAddr))
|
||||
pFilter->SetFilter(&FilterInfo);
|
||||
|
||||
// player country
|
||||
{
|
||||
CUIRect Rect;
|
||||
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
|
||||
ServerFilter.HSplitTop(26.0f, &Button, &ServerFilter);
|
||||
Button.VSplitRight(60.0f, &Button, &Rect);
|
||||
Button.HMargin(3.0f, &Button);
|
||||
static int s_BrFilterCountry = 0;
|
||||
if(pMenus->DoButton_CheckBox(&s_BrFilterCountry, Localize("Player country:"), FilterInfo.m_SortHash&IServerBrowser::FILTER_COUNTRY, &Button))
|
||||
{
|
||||
FilterInfo.m_SortHash = FilterInfo.m_SortHash^IServerBrowser::FILTER_COUNTRY;
|
||||
pFilter->SetFilter(&FilterInfo);
|
||||
}
|
||||
|
||||
float OldWidth = Rect.w;
|
||||
Rect.w = Rect.h*2;
|
||||
Rect.x += (OldWidth-Rect.w)/2.0f;
|
||||
vec4 Color(1.0f, 1.0f, 1.0f, FilterInfo.m_SortHash^IServerBrowser::FILTER_COUNTRY?1.0f: 0.5f);
|
||||
pMenus->m_pClient->m_pCountryFlags->Render(FilterInfo.m_Country, &Color, Rect.x, Rect.y, Rect.w, Rect.h);
|
||||
|
||||
static int s_BrFilterCountryIndex = 0;
|
||||
if(FilterInfo.m_SortHash^IServerBrowser::FILTER_COUNTRY && pMenus->UI()->DoButtonLogic(&s_BrFilterCountryIndex, "", 0, &Rect))
|
||||
pMenus->m_Popup = POPUP_COUNTRY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <generated/protocol.h>
|
||||
#include <generated/client_data.h>
|
||||
|
||||
#include <game/client/components/maplayers.h>
|
||||
#include <game/client/components/sounds.h>
|
||||
#include <game/client/ui.h>
|
||||
#include <game/client/render.h>
|
||||
|
@ -577,6 +578,93 @@ public:
|
|||
bool operator<(const CLanguage &Other) { return m_Name < Other.m_Name; }
|
||||
};
|
||||
|
||||
|
||||
int CMenus::ThemeScan(const char *pName, int IsDir, int DirType, void *pUser)
|
||||
{
|
||||
CMenus *pSelf = (CMenus *)pUser;
|
||||
int l = str_length(pName);
|
||||
|
||||
if(l < 5 || IsDir || str_comp(pName+l-4, ".map") != 0)
|
||||
return 0;
|
||||
char aFullName[128];
|
||||
char aThemeName[128];
|
||||
str_copy(aFullName, pName, min((int)sizeof(aFullName),l-3));
|
||||
|
||||
l = str_length(aFullName);
|
||||
bool isDay = false;
|
||||
bool isNight = false;
|
||||
if(l > 4 && str_comp(aFullName+l-4, "_day") == 0)
|
||||
{
|
||||
str_copy(aThemeName, pName, min((int)sizeof(aThemeName),l-3));
|
||||
isDay = true;
|
||||
}
|
||||
else if(l > 6 && str_comp(aFullName+l-6, "_night") == 0)
|
||||
{
|
||||
str_copy(aThemeName, pName, min((int)sizeof(aThemeName),l-5));
|
||||
isNight = true;
|
||||
}
|
||||
else
|
||||
str_copy(aThemeName, aFullName, sizeof(aThemeName));
|
||||
|
||||
if(str_comp(aThemeName, "none") == 0) // "none" is reserved, disallowed for maps
|
||||
return 0;
|
||||
|
||||
// try to edit an existing theme
|
||||
for(int i = 0; i < pSelf->m_lThemes.size(); i++)
|
||||
{
|
||||
if(str_comp(pSelf->m_lThemes[i].m_Name, aThemeName) == 0)
|
||||
{
|
||||
if(isDay)
|
||||
pSelf->m_lThemes[i].m_HasDay = true;
|
||||
if(isNight)
|
||||
pSelf->m_lThemes[i].m_HasNight = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// make new theme
|
||||
CTheme Theme(aThemeName, isDay, isNight);
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof(aBuf), "added theme %s from ui/themes/%s", aThemeName, pName);
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
|
||||
pSelf->m_lThemes.add(Theme);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMenus::ThemeIconScan(const char *pName, int IsDir, int DirType, void *pUser)
|
||||
{
|
||||
CMenus *pSelf = (CMenus *)pUser;
|
||||
int l = str_length(pName);
|
||||
|
||||
if(l < 4 || IsDir || str_comp(pName+l-4, ".png") != 0)
|
||||
return 0;
|
||||
char aThemeName[128];
|
||||
str_copy(aThemeName, pName, min((int)sizeof(aThemeName),l-3));
|
||||
|
||||
// save icon for an existing theme
|
||||
for(sorted_array<CTheme>::range r = pSelf->m_lThemes.all(); !r.empty(); r.pop_front()) // bit slow but whatever
|
||||
{
|
||||
if(str_comp(r.front().m_Name, aThemeName) == 0 || (!r.front().m_Name[0] && str_comp(aThemeName, "none") == 0))
|
||||
{
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof(aBuf), "ui/themes/%s", pName);
|
||||
CImageInfo Info;
|
||||
if(!pSelf->Graphics()->LoadPNG(&Info, aBuf, DirType))
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "failed to load theme icon from %s", pName);
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
|
||||
return 0;
|
||||
}
|
||||
str_format(aBuf, sizeof(aBuf), "loaded theme icon %s", pName);
|
||||
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
|
||||
|
||||
r.front().m_IconTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0; // no existing theme
|
||||
}
|
||||
|
||||
void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array<CLanguage> *pLanguages)
|
||||
{
|
||||
// read file data into buffer
|
||||
|
@ -588,20 +676,20 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array<
|
|||
return;
|
||||
}
|
||||
int FileSize = (int)io_length(File);
|
||||
char *pFileData = (char *)mem_alloc(FileSize+1, 1);
|
||||
char *pFileData = (char *)mem_alloc(FileSize, 1);
|
||||
io_read(File, pFileData, FileSize);
|
||||
pFileData[FileSize] = 0;
|
||||
io_close(File);
|
||||
|
||||
// parse json data
|
||||
json_settings JsonSettings;
|
||||
mem_zero(&JsonSettings, sizeof(JsonSettings));
|
||||
char aError[256];
|
||||
json_value *pJsonData = json_parse_ex(&JsonSettings, pFileData, aError);
|
||||
json_value *pJsonData = json_parse_ex(&JsonSettings, pFileData, FileSize, aError);
|
||||
mem_free(pFileData);
|
||||
|
||||
if(pJsonData == 0)
|
||||
{
|
||||
pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, pFilename, aError);
|
||||
mem_free(pFileData);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -613,19 +701,19 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array<
|
|||
{
|
||||
char aFileName[128];
|
||||
str_format(aFileName, sizeof(aFileName), "languages/%s.json", (const char *)rStart[i]["file"]);
|
||||
pLanguages->add(CLanguage((const char *)rStart[i]["name"], aFileName, (long)rStart[i]["code"]));
|
||||
pLanguages->add(CLanguage((const char *)rStart[i]["name"], aFileName, (json_int_t)rStart[i]["code"]));
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
json_value_free(pJsonData);
|
||||
mem_free(pFileData);
|
||||
}
|
||||
|
||||
void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header)
|
||||
{
|
||||
static int s_LanguageList = 0;
|
||||
static int s_SelectedLanguage = 0;
|
||||
static int s_SelectedLanguage = -1;
|
||||
static int s_OldSelected = -1;
|
||||
static sorted_array<CLanguage> s_Languages;
|
||||
static CListBoxState s_ListBoxState;
|
||||
|
||||
|
@ -641,6 +729,17 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header)
|
|||
}
|
||||
}
|
||||
|
||||
if(s_SelectedLanguage != -1 && m_ActiveListBox != ACTLB_LANG)
|
||||
{
|
||||
s_OldSelected = s_SelectedLanguage;
|
||||
s_SelectedLanguage = -1;
|
||||
}
|
||||
static int s_LangID = 0;
|
||||
if(s_SelectedLanguage == -1 && UI()->MouseInside(&MainView))
|
||||
{
|
||||
s_SelectedLanguage = s_OldSelected;
|
||||
m_ActiveListBox = ACTLB_LANG;
|
||||
}
|
||||
int OldSelected = s_SelectedLanguage;
|
||||
|
||||
if(Header)
|
||||
|
@ -660,7 +759,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header)
|
|||
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
m_pClient->m_pCountryFlags->Render(r.front().m_CountryCode, &Color, Rect.x, Rect.y, Rect.w, Rect.h);
|
||||
Item.m_Rect.y += 2.0f;
|
||||
if(!str_comp(s_Languages[s_SelectedLanguage].m_Name, r.front().m_Name))
|
||||
if(s_SelectedLanguage != -1 && !str_comp(s_Languages[s_SelectedLanguage].m_Name, r.front().m_Name))
|
||||
{
|
||||
TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f);
|
||||
|
@ -677,25 +776,133 @@ void CMenus::RenderLanguageSelection(CUIRect MainView, bool Header)
|
|||
|
||||
if(OldSelected != s_SelectedLanguage)
|
||||
{
|
||||
m_ActiveListBox = ACTLB_LANG;
|
||||
str_copy(g_Config.m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(g_Config.m_ClLanguagefile));
|
||||
g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName, Storage(), Console());
|
||||
}
|
||||
}
|
||||
|
||||
void CMenus::RenderThemeSelection(CUIRect MainView, bool Header)
|
||||
{
|
||||
static int s_ThemeList = 0;
|
||||
static int s_SelectedTheme = -1;
|
||||
static int s_OldSelected = -1;
|
||||
static CListBoxState s_ListBoxState_Theme;
|
||||
|
||||
if(m_lThemes.size() == 0) // not loaded yet
|
||||
{
|
||||
m_lThemes.add(CTheme("", false, false)); // no theme
|
||||
Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeScan, (CMenus*)this);
|
||||
Storage()->ListDirectory(IStorage::TYPE_ALL, "ui/themes", ThemeIconScan, (CMenus*)this);
|
||||
for(int i = 0; i < m_lThemes.size(); i++)
|
||||
if(str_comp(m_lThemes[i].m_Name, g_Config.m_ClMenuMap) == 0)
|
||||
{
|
||||
s_SelectedTheme = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(s_SelectedTheme != -1 && m_ActiveListBox != ACTLB_THEME)
|
||||
{
|
||||
s_OldSelected = s_SelectedTheme;
|
||||
s_SelectedTheme = -1;
|
||||
}
|
||||
if(s_SelectedTheme == -1 && UI()->MouseInside(&MainView))
|
||||
{
|
||||
s_SelectedTheme = s_OldSelected;
|
||||
m_ActiveListBox = ACTLB_THEME;
|
||||
}
|
||||
int OldSelected = s_SelectedTheme;
|
||||
|
||||
if(Header)
|
||||
UiDoListboxHeader(&s_ListBoxState_Theme, &MainView, Localize("Theme"), 20.0f, 2.0f);
|
||||
UiDoListboxStart(&s_ListBoxState_Theme, &s_ThemeList, 20.0f, 0, m_lThemes.size(), 1, s_SelectedTheme, Header?0:&MainView, Header?true:false);
|
||||
|
||||
for(sorted_array<CTheme>::range r = m_lThemes.all(); !r.empty(); r.pop_front())
|
||||
{
|
||||
CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState_Theme, &r.front());
|
||||
|
||||
if(Item.m_Visible)
|
||||
{
|
||||
CUIRect Rect;
|
||||
Item.m_Rect.VSplitLeft(Item.m_Rect.h*2.0f, &Rect, &Item.m_Rect);
|
||||
Rect.VMargin(6.0f, &Rect);
|
||||
Rect.HMargin(3.0f, &Rect);
|
||||
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// draw icon if it exists
|
||||
if(r.front().m_IconTexture.IsValid())
|
||||
{
|
||||
Graphics()->TextureSet(r.front().m_IconTexture);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
IGraphics::CQuadItem QuadItem(Rect.x, Rect.y, Rect.w, Rect.h);
|
||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
}
|
||||
|
||||
Item.m_Rect.y += 2.0f;
|
||||
char aName[128];
|
||||
if(r.front().m_Name[0])
|
||||
{
|
||||
if(r.front().m_HasDay && r.front().m_HasNight)
|
||||
str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr());
|
||||
else if(r.front().m_HasDay && !r.front().m_HasNight)
|
||||
str_format(aName, sizeof(aName), "%s (day)", r.front().m_Name.cstr());
|
||||
else if(!r.front().m_HasDay && r.front().m_HasNight)
|
||||
str_format(aName, sizeof(aName), "%s (night)", r.front().m_Name.cstr());
|
||||
else // generic
|
||||
str_format(aName, sizeof(aName), "%s", r.front().m_Name.cstr());
|
||||
}
|
||||
else
|
||||
str_copy(aName, "(none)", sizeof(aName));
|
||||
|
||||
if(s_SelectedTheme != -1 && !str_comp(m_lThemes[s_SelectedTheme].m_Name, r.front().m_Name))
|
||||
{
|
||||
TextRender()->TextColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
TextRender()->TextOutlineColor(1.0f, 1.0f, 1.0f, 0.25f);
|
||||
UI()->DoLabelScaled(&Item.m_Rect, aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
}
|
||||
else
|
||||
UI()->DoLabelScaled(&Item.m_Rect, aName, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
s_SelectedTheme = UiDoListboxEnd(&s_ListBoxState_Theme, 0);
|
||||
|
||||
if(OldSelected != s_SelectedTheme)
|
||||
{
|
||||
m_ActiveListBox = ACTLB_THEME;
|
||||
str_copy(g_Config.m_ClMenuMap, m_lThemes[s_SelectedTheme].m_Name, sizeof(g_Config.m_ClMenuMap));
|
||||
if(m_lThemes[s_SelectedTheme].m_Name[0])
|
||||
g_Config.m_ClShowMenuMap = 1;
|
||||
else
|
||||
g_Config.m_ClShowMenuMap = 0;
|
||||
m_pClient->m_pMapLayersBackGround->BackgroundMapUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void CMenus::RenderSettingsGeneral(CUIRect MainView)
|
||||
{
|
||||
CUIRect Label, Button, Game, Client, BottomView;
|
||||
CUIRect Label, Button, Game, Client, BottomView, Background;
|
||||
|
||||
// cut view
|
||||
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
||||
BottomView.HSplitTop(20.f, 0, &BottomView);
|
||||
|
||||
// render game menu backgrounds
|
||||
int NumOptions = g_Config.m_ClNameplates ? 9 : 6;
|
||||
int NumOptions = g_Config.m_ClNameplates ? 6 : 3;
|
||||
float ButtonHeight = 20.0f;
|
||||
float Spacing = 2.0f;
|
||||
float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing;
|
||||
|
||||
if(this->Client()->State() == IClient::STATE_ONLINE)
|
||||
Background = MainView;
|
||||
else
|
||||
MainView.HSplitTop(20.0f, 0, &Background);
|
||||
RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), this->Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitTop(BackgroundHeight, &Game, &MainView);
|
||||
RenderTools()->DrawUIRect(&Game, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
@ -710,46 +917,99 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
|
|||
MainView.HSplitTop(BackgroundHeight, &Client, &MainView);
|
||||
RenderTools()->DrawUIRect(&Client, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
CUIRect GameLeft, GameRight;
|
||||
// render game menu
|
||||
Game.HSplitTop(ButtonHeight, &Label, &Game);
|
||||
Label.y += 2.0f;
|
||||
UI()->DoLabel(&Label, Localize("Game"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
Game.VSplitMid(&GameLeft, &GameRight);
|
||||
GameLeft.VSplitRight(Spacing * 0.5f, &GameLeft, 0);
|
||||
GameRight.VSplitLeft(Spacing * 0.5f, 0, &GameRight);
|
||||
|
||||
// left side
|
||||
GameLeft.HSplitTop(Spacing, 0, &GameLeft);
|
||||
GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft);
|
||||
static int s_DynamicCameraButton = 0;
|
||||
if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClMouseDeadzone != 0, &Button))
|
||||
if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClDynamicCamera, &Button))
|
||||
{
|
||||
if(g_Config.m_ClMouseDeadzone)
|
||||
if(g_Config.m_ClDynamicCamera)
|
||||
{
|
||||
g_Config.m_ClMouseFollowfactor = 0;
|
||||
g_Config.m_ClMouseMaxDistance = 400;
|
||||
g_Config.m_ClMouseDeadzone = 0;
|
||||
g_Config.m_ClDynamicCamera = 0;
|
||||
// force to defaults when using the GUI
|
||||
g_Config.m_ClMouseMaxDistanceStatic = 400;
|
||||
// g_Config.m_ClMouseFollowfactor = 0;
|
||||
// g_Config.m_ClMouseDeadzone = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Config.m_ClDynamicCamera = 1;
|
||||
// force to defaults when using the GUI
|
||||
g_Config.m_ClMouseMaxDistanceDynamic = 1000;
|
||||
g_Config.m_ClMouseFollowfactor = 60;
|
||||
g_Config.m_ClMouseMaxDistance = 1000;
|
||||
g_Config.m_ClMouseDeadzone = 300;
|
||||
}
|
||||
}
|
||||
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
GameLeft.HSplitTop(Spacing, 0, &GameLeft);
|
||||
GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft);
|
||||
static int s_AutoswitchWeapons = 0;
|
||||
if(DoButton_CheckBox(&s_AutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button))
|
||||
g_Config.m_ClAutoswitchWeapons ^= 1;
|
||||
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
GameLeft.HSplitTop(Spacing, 0, &GameLeft);
|
||||
GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft);
|
||||
static int s_Nameplates = 0;
|
||||
if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button))
|
||||
g_Config.m_ClNameplates ^= 1;
|
||||
|
||||
if(g_Config.m_ClNameplates)
|
||||
{
|
||||
GameLeft.HSplitTop(Spacing, 0, &GameLeft);
|
||||
GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
static int s_NameplatesAlways = 0;
|
||||
if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button))
|
||||
g_Config.m_ClNameplatesAlways ^= 1;
|
||||
|
||||
GameLeft.HSplitTop(Spacing, 0, &GameLeft);
|
||||
GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
DoScrollbarOption(&g_Config.m_ClNameplatesSize, &g_Config.m_ClNameplatesSize, &Button, Localize("Size"), 100.0f, 0, 100);
|
||||
|
||||
GameLeft.HSplitTop(Spacing, 0, &GameLeft);
|
||||
GameLeft.HSplitTop(ButtonHeight, &Button, &GameLeft);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
static int s_NameplatesTeamcolors = 0;
|
||||
if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), g_Config.m_ClNameplatesTeamcolors, &Button))
|
||||
g_Config.m_ClNameplatesTeamcolors ^= 1;
|
||||
}
|
||||
|
||||
// right side
|
||||
GameRight.HSplitTop(Spacing, 0, &GameRight);
|
||||
GameRight.HSplitTop(ButtonHeight, &Button, &GameRight);
|
||||
static int s_Showhud = 0;
|
||||
if(DoButton_CheckBox(&s_Showhud, Localize("Show ingame HUD"), g_Config.m_ClShowhud, &Button))
|
||||
g_Config.m_ClShowhud ^= 1;
|
||||
|
||||
GameRight.HSplitTop(Spacing, 0, &GameRight);
|
||||
GameRight.HSplitTop(ButtonHeight, &Button, &GameRight);
|
||||
static int s_Showsocial = 0;
|
||||
if(DoButton_CheckBox(&s_Showsocial, Localize("Show social"), g_Config.m_ClShowsocial, &Button))
|
||||
g_Config.m_ClShowsocial ^= 1;
|
||||
|
||||
GameRight.HSplitTop(Spacing, 0, &GameRight);
|
||||
GameRight.HSplitTop(ButtonHeight, &Button, &GameRight);
|
||||
static int s_ShowUserId = 0;
|
||||
if(DoButton_CheckBox(&s_ShowUserId, Localize("Show user IDs"), g_Config.m_ClShowUserId, &Button))
|
||||
g_Config.m_ClShowUserId ^= 1;
|
||||
|
||||
// show chat messages button
|
||||
if(g_Config.m_ClShowsocial)
|
||||
{
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
GameRight.HSplitTop(Spacing, 0, &GameRight);
|
||||
GameRight.HSplitTop(ButtonHeight, &Button, &GameRight);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
CUIRect Text;
|
||||
Button.VSplitLeft(ButtonHeight+5.0f, 0, &Button);
|
||||
|
@ -760,52 +1020,18 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
|
|||
Text.y += 2.0f;
|
||||
UI()->DoLabel(&Text, aBuf, Text.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
|
||||
|
||||
Button.VSplitLeft(100.0f, &Button, 0);
|
||||
Button.VSplitLeft(119.0f, &Button, 0);
|
||||
if(g_Config.m_ClFilterchat == 0)
|
||||
str_format(aBuf, sizeof(aBuf), "everyone");
|
||||
str_format(aBuf, sizeof(aBuf), Localize("everyone"));
|
||||
else if(g_Config.m_ClFilterchat == 1)
|
||||
str_format(aBuf, sizeof(aBuf), "friends only");
|
||||
str_format(aBuf, sizeof(aBuf), Localize("friends only"));
|
||||
else if(g_Config.m_ClFilterchat == 2)
|
||||
str_format(aBuf, sizeof(aBuf), "no one");
|
||||
str_format(aBuf, sizeof(aBuf), Localize("no one"));
|
||||
static CButtonContainer s_ButtonFilterchat;
|
||||
if(DoButton_Menu(&s_ButtonFilterchat, aBuf, 0, &Button))
|
||||
g_Config.m_ClFilterchat = (g_Config.m_ClFilterchat + 1) % 3;
|
||||
}
|
||||
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
static int s_Showsocial = 0;
|
||||
if(DoButton_CheckBox(&s_Showsocial, Localize("Show social"), g_Config.m_ClShowsocial, &Button))
|
||||
g_Config.m_ClShowsocial ^= 1;
|
||||
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
static int s_Nameplates = 0;
|
||||
if(DoButton_CheckBox(&s_Nameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button))
|
||||
g_Config.m_ClNameplates ^= 1;
|
||||
|
||||
if(g_Config.m_ClNameplates)
|
||||
{
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
static int s_NameplatesAlways = 0;
|
||||
if(DoButton_CheckBox(&s_NameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button))
|
||||
g_Config.m_ClNameplatesAlways ^= 1;
|
||||
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
DoScrollbarOption(&g_Config.m_ClNameplatesSize, &g_Config.m_ClNameplatesSize, &Button, Localize("Size"), 100.0f, 0, 100);
|
||||
|
||||
Game.HSplitTop(Spacing, 0, &Game);
|
||||
Game.HSplitTop(ButtonHeight, &Button, &Game);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
static int s_NameplatesTeamcolors = 0;
|
||||
if(DoButton_CheckBox(&s_NameplatesTeamcolors, Localize("Use team colors for name plates"), g_Config.m_ClNameplatesTeamcolors, &Button))
|
||||
g_Config.m_ClNameplatesTeamcolors ^= 1;
|
||||
}
|
||||
|
||||
// render client menu
|
||||
Client.HSplitTop(ButtonHeight, &Label, &Client);
|
||||
Label.y += 2.0f;
|
||||
|
@ -847,8 +1073,13 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
|
|||
|
||||
MainView.HSplitTop(10.0f, 0, &MainView);
|
||||
|
||||
// render language selection
|
||||
RenderLanguageSelection(MainView);
|
||||
// render language and theme selection
|
||||
CUIRect LanguageView, ThemeView;
|
||||
MainView.VSplitMid(&LanguageView, &ThemeView);
|
||||
LanguageView.VSplitRight(1, &LanguageView, 0);
|
||||
ThemeView.VSplitLeft(1, 0, &ThemeView);
|
||||
RenderLanguageSelection(LanguageView);
|
||||
RenderThemeSelection(ThemeView);
|
||||
|
||||
// reset button
|
||||
Spacing = 3.0f;
|
||||
|
@ -862,8 +1093,9 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
|
|||
static CButtonContainer s_ResetButton;
|
||||
if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button))
|
||||
{
|
||||
g_Config.m_ClDynamicCamera = 1;
|
||||
g_Config.m_ClMouseMaxDistanceDynamic = 1000;
|
||||
g_Config.m_ClMouseFollowfactor = 60;
|
||||
g_Config.m_ClMouseMaxDistance = 1000;
|
||||
g_Config.m_ClMouseDeadzone = 300;
|
||||
g_Config.m_ClAutoswitchWeapons = 1;
|
||||
g_Config.m_ClShowhud = 1;
|
||||
|
@ -881,15 +1113,20 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
|
|||
|
||||
void CMenus::RenderSettingsPlayer(CUIRect MainView)
|
||||
{
|
||||
CUIRect Button, Left, Right, TopView, Label;
|
||||
CUIRect Button, Left, Right, TopView, Label, Background;
|
||||
|
||||
// render game menu backgrounds
|
||||
float ButtonHeight = 20.0f;
|
||||
float Spacing = 2.0f;
|
||||
float BackgroundHeight = 2.0f*ButtonHeight+Spacing;
|
||||
|
||||
MainView.HSplitBottom(80.0f, &MainView, 0); // now we have the total rect for the settings#
|
||||
if(this->Client()->State() == IClient::STATE_ONLINE)
|
||||
Background = MainView;
|
||||
else
|
||||
MainView.HSplitTop(20.0f, 0, &Background);
|
||||
RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitBottom(80.0f, &MainView, 0); // now we have the total rect for the settings
|
||||
MainView.HSplitTop(BackgroundHeight, &TopView, &MainView);
|
||||
RenderTools()->DrawUIRect(&TopView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
|
@ -975,10 +1212,7 @@ void CMenus::RenderSettingsTeeCustom(CUIRect MainView)
|
|||
float SpacingH = 2.0f;
|
||||
float SpacingW = 3.0f;
|
||||
float ButtonHeight = 20.0f;
|
||||
float BoxSize = 297.0f;
|
||||
float BackgroundHeight = (ButtonHeight+SpacingH)*3.0f+BoxSize;
|
||||
|
||||
MainView.HSplitTop(BackgroundHeight, &MainView, 0);
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
MainView.HSplitTop(ButtonHeight, &Label, &MainView);
|
||||
|
@ -1019,7 +1253,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
|||
{
|
||||
static bool s_CustomSkinMenu = false;
|
||||
|
||||
CUIRect Button, Label, BottomView, Preview;
|
||||
CUIRect Button, Label, BottomView, Preview, Background;
|
||||
|
||||
// cut view
|
||||
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
||||
|
@ -1034,6 +1268,11 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
|||
if(!s_CustomSkinMenu)
|
||||
BackgroundHeight = (ButtonHeight+SpacingH)*2.0f+SkinHeight;
|
||||
|
||||
if(this->Client()->State() == IClient::STATE_ONLINE)
|
||||
Background = MainView;
|
||||
else
|
||||
MainView.HSplitTop(20.0f, 0, &Background);
|
||||
RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitTop(BackgroundHeight, &Preview, &MainView);
|
||||
RenderTools()->DrawUIRect(&Preview, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
@ -1167,33 +1406,81 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
|
|||
|
||||
void CMenus::RenderSettingsControls(CUIRect MainView)
|
||||
{
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
|
||||
// cut view
|
||||
CUIRect BottomView, Button;
|
||||
CUIRect BottomView, Button, Background;
|
||||
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
||||
if(this->Client()->State() == IClient::STATE_ONLINE)
|
||||
Background = MainView;
|
||||
else
|
||||
MainView.HSplitTop(20.0f, 0, &Background);
|
||||
RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
BottomView.HSplitTop(20.f, 0, &BottomView);
|
||||
|
||||
float HeaderHeight = 20.0f;
|
||||
// split scrollbar from main view
|
||||
CUIRect Scroll;
|
||||
MainView.VSplitRight(20.0f, &MainView, &Scroll);
|
||||
RenderTools()->DrawUIRect(&Scroll, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
RenderTools()->DrawUIRect(&MainView, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
||||
const float HeaderHeight = 20.0f;
|
||||
const float ItemHeight = 20.0f+2.0f;
|
||||
const float MainViewH = MainView.h;
|
||||
|
||||
// make scrollbar
|
||||
static int s_ScrollBar = 0;
|
||||
static int s_ScrollNum = 0;
|
||||
static float s_ScrollValue = 0.f;
|
||||
static float TotalHeight = 0.f;
|
||||
Scroll.HMargin(5.0f, &Scroll);
|
||||
s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
|
||||
|
||||
UI()->ClipEnable(&MainView);
|
||||
if(TotalHeight - MainView.h > 0)
|
||||
MainView.y -= s_ScrollValue*(TotalHeight - MainView.h);
|
||||
|
||||
TotalHeight = 0.f;
|
||||
static int s_MovementDropdown = 0;
|
||||
float Split = DoDropdownMenu(&s_MovementDropdown, &MainView, Localize("Movement"), HeaderHeight, RenderSettingsControlsMovement);
|
||||
static bool s_MovementActive = true;
|
||||
float Split = DoIndependentDropdownMenu(&s_MovementDropdown, &MainView, Localize("Movement"), HeaderHeight, RenderSettingsControlsMovement, &s_MovementActive);
|
||||
|
||||
TotalHeight += Split+10.0f;
|
||||
MainView.HSplitTop(Split+10.0f, 0, &MainView);
|
||||
static int s_WeaponDropdown = 0;
|
||||
Split = DoDropdownMenu(&s_WeaponDropdown, &MainView, Localize("Weapon"), HeaderHeight, RenderSettingsControlsWeapon);
|
||||
static bool s_WeaponActive = true;
|
||||
Split = DoIndependentDropdownMenu(&s_WeaponDropdown, &MainView, Localize("Weapon"), HeaderHeight, RenderSettingsControlsWeapon, &s_WeaponActive);
|
||||
|
||||
TotalHeight += Split+10.0f;
|
||||
MainView.HSplitTop(Split+10.0f, 0, &MainView);
|
||||
static int s_VotingDropdown = 0;
|
||||
Split = DoDropdownMenu(&s_VotingDropdown, &MainView, Localize("Voting"), HeaderHeight, RenderSettingsControlsVoting);
|
||||
static bool s_VotingActive = true;
|
||||
Split = DoIndependentDropdownMenu(&s_VotingDropdown, &MainView, Localize("Voting"), HeaderHeight, RenderSettingsControlsVoting, &s_VotingActive);
|
||||
|
||||
TotalHeight += Split+10.0f;
|
||||
MainView.HSplitTop(Split+10.0f, 0, &MainView);
|
||||
static int s_ChatDropdown = 0;
|
||||
Split = DoDropdownMenu(&s_ChatDropdown, &MainView, Localize("Chat"), HeaderHeight, RenderSettingsControlsChat);
|
||||
static bool s_ChatActive = true;
|
||||
Split = DoIndependentDropdownMenu(&s_ChatDropdown, &MainView, Localize("Chat"), HeaderHeight, RenderSettingsControlsChat, &s_ChatActive);
|
||||
|
||||
TotalHeight += Split+10.0f;
|
||||
MainView.HSplitTop(Split+10.0f, 0, &MainView);
|
||||
static int s_MiscDropdown = 0;
|
||||
Split = DoDropdownMenu(&s_MiscDropdown, &MainView, Localize("Misc"), HeaderHeight, RenderSettingsControlsMisc);
|
||||
static bool s_MiscActive = true;
|
||||
Split = DoIndependentDropdownMenu(&s_MiscDropdown, &MainView, Localize("Misc"), HeaderHeight, RenderSettingsControlsMisc, &s_MiscActive);
|
||||
TotalHeight += Split;
|
||||
UI()->ClipDisable();
|
||||
|
||||
// handle scrolling
|
||||
float ProperHeight = (TotalHeight-5*HeaderHeight-40.0f);
|
||||
s_ScrollNum = /*ceil*/((ProperHeight-MainViewH)/ItemHeight);
|
||||
if(s_ScrollNum <= 0)
|
||||
s_ScrollNum = 1;
|
||||
// We could && UI()->MouseInside(&MainView)), but that does not work well because the controls settings menu got holes
|
||||
if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP))
|
||||
s_ScrollValue -= 3.0f/s_ScrollNum; // will be set to 0 by clamp if scrollnum is too small
|
||||
if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN))
|
||||
s_ScrollValue += 3.0f/s_ScrollNum; // will be set to 1 by clamp if scrollnum is too small
|
||||
s_ScrollValue = clamp(s_ScrollValue, 0.f, 1.f);
|
||||
|
||||
// reset button
|
||||
float Spacing = 3.0f;
|
||||
|
@ -1276,20 +1563,25 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
static int s_GfxTextureQuality = g_Config.m_GfxTextureQuality;
|
||||
static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression;
|
||||
|
||||
CUIRect Label, Button, ScreenLeft, ScreenRight, Texture, BottomView;
|
||||
CUIRect Label, Button, ScreenLeft, ScreenRight, Texture, BottomView, Background;
|
||||
|
||||
// cut view
|
||||
MainView.HSplitBottom(80.0f, &MainView, &BottomView);
|
||||
BottomView.HSplitTop(20.f, 0, &BottomView);
|
||||
|
||||
// render screen menu background
|
||||
int NumOptions = 3 + (!g_Config.m_GfxFullscreen);
|
||||
int NumOptions = 3;// + (!g_Config.m_GfxFullscreen);
|
||||
if(Graphics()->GetNumScreens() > 1)
|
||||
++NumOptions;
|
||||
float ButtonHeight = 20.0f;
|
||||
float Spacing = 2.0f;
|
||||
float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing;
|
||||
|
||||
if(this->Client()->State() == IClient::STATE_ONLINE)
|
||||
Background = MainView;
|
||||
else
|
||||
MainView.HSplitTop(20.0f, 0, &Background);
|
||||
RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitTop(BackgroundHeight, &ScreenLeft, &MainView);
|
||||
RenderTools()->DrawUIRect(&ScreenLeft, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
@ -1327,12 +1619,6 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
Client()->ToggleWindowBordered();
|
||||
}
|
||||
|
||||
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||
ScreenLeft.HSplitTop(ButtonHeight, &Button, &ScreenLeft);
|
||||
static int s_ButtonGfxVsync = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button))
|
||||
Client()->ToggleWindowVSync();
|
||||
|
||||
// FSAA button
|
||||
{
|
||||
ScreenLeft.HSplitTop(Spacing, 0, &ScreenLeft);
|
||||
|
@ -1362,6 +1648,12 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
}
|
||||
}
|
||||
|
||||
ScreenRight.HSplitTop(Spacing, 0, &ScreenRight);
|
||||
ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight);
|
||||
static int s_ButtonGfxVsync = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonGfxVsync, Localize("V-Sync"), g_Config.m_GfxVsync, &Button))
|
||||
Client()->ToggleWindowVSync();
|
||||
|
||||
ScreenRight.HSplitTop(Spacing, 0, &ScreenRight);
|
||||
ScreenRight.HSplitTop(ButtonHeight, &Button, &ScreenRight);
|
||||
|
||||
|
@ -1449,7 +1741,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
RenderTools()->DrawUIRect(&HeaderLeft, vec4(0.30f, 0.4f, 1.0f, 0.5f), CUI::CORNER_T, 5.0f);
|
||||
RenderTools()->DrawUIRect(&HeaderRight, vec4(0.0f, 0.0f, 0.0f, 0.5f), CUI::CORNER_T, 5.0f);
|
||||
|
||||
char aBuf[32];
|
||||
char aBuf[64];
|
||||
str_format(aBuf, sizeof(aBuf), "%s", Localize("Recommended"));
|
||||
HeaderLeft.y += 2;
|
||||
UI()->DoLabel(&HeaderLeft, aBuf, HeaderLeft.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
|
@ -1462,6 +1754,15 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
MainView.HSplitTop(Spacing, 0, &MainView);
|
||||
CUIRect ListRec, ListOth;
|
||||
MainView.VSplitMid(&ListRec, &ListOth);
|
||||
|
||||
ListRec.HSplitBottom(ButtonHeight, &ListRec, &Button);
|
||||
ListRec.HSplitBottom(Spacing, &ListRec, 0);
|
||||
RenderTools()->DrawUIRect(&Button, vec4(0.0f, 0.0f, 0.0f, 0.5f), CUI::CORNER_B, 5.0f);
|
||||
int g = gcd(s_GfxScreenWidth, s_GfxScreenHeight);
|
||||
str_format(aBuf, sizeof(aBuf), Localize("Current: %dx%d (%d:%d)"), s_GfxScreenWidth, s_GfxScreenHeight, s_GfxScreenWidth/g, s_GfxScreenHeight/g);
|
||||
Button.y += 2;
|
||||
UI()->DoLabel(&Button, aBuf, Button.h*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
|
||||
ListRec.VSplitRight(1.5f, &ListRec, 0);
|
||||
ListOth.VSplitLeft(1.5f, 0, &ListOth);
|
||||
|
||||
|
@ -1518,14 +1819,23 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
|
|||
|
||||
void CMenus::RenderSettingsSound(CUIRect MainView)
|
||||
{
|
||||
CUIRect Label, Button, Sound, Detail, BottomView;
|
||||
CUIRect Label, Button, Sound, Detail, BottomView, Background;
|
||||
|
||||
// render sound menu background
|
||||
int NumOptions = g_Config.m_SndEnable ? 3 : 1;
|
||||
int NumOptions = g_Config.m_SndEnable ? 3 : 2;
|
||||
float ButtonHeight = 20.0f;
|
||||
float Spacing = 2.0f;
|
||||
float BackgroundHeight = (float)(NumOptions+1)*ButtonHeight+(float)NumOptions*Spacing;
|
||||
float TotalHeight = BackgroundHeight;
|
||||
if(g_Config.m_SndEnable)
|
||||
TotalHeight += 10.0f+2.0f*ButtonHeight+Spacing;
|
||||
|
||||
MainView.HSplitBottom(MainView.h-TotalHeight-20.0f, &MainView, &BottomView);
|
||||
if(this->Client()->State() == IClient::STATE_ONLINE)
|
||||
Background = MainView;
|
||||
else
|
||||
MainView.HSplitTop(20.0f, 0, &Background);
|
||||
RenderTools()->DrawUIRect(&Background, vec4(0.0f, 0.0f, 0.0f, ms_BackgroundAlpha), Client()->State() == IClient::STATE_OFFLINE ? CUI::CORNER_ALL : CUI::CORNER_B, 5.0f);
|
||||
MainView.HSplitTop(20.0f, 0, &MainView);
|
||||
MainView.HSplitTop(BackgroundHeight, &Sound, &MainView);
|
||||
RenderTools()->DrawUIRect(&Sound, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
|
@ -1540,7 +1850,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
|
|||
RenderTools()->DrawUIRect(&Detail, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
|
||||
}
|
||||
|
||||
static int s_SndEnable = g_Config.m_SndEnable;
|
||||
static int s_SndInit = g_Config.m_SndInit;
|
||||
static int s_SndRate = g_Config.m_SndRate;
|
||||
|
||||
// render sound menu
|
||||
|
@ -1549,20 +1859,8 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
|
|||
UI()->DoLabel(&Label, Localize("Sound"), ButtonHeight*ms_FontmodHeight*0.8f, CUI::ALIGN_CENTER);
|
||||
|
||||
Sound.HSplitTop(Spacing, 0, &Sound);
|
||||
Sound.HSplitTop(ButtonHeight, &Button, &Sound);
|
||||
static int s_ButtonSndEnable = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonSndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &Button))
|
||||
{
|
||||
g_Config.m_SndEnable ^= 1;
|
||||
if(g_Config.m_SndEnable)
|
||||
{
|
||||
if(g_Config.m_SndMusic)
|
||||
m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
|
||||
}
|
||||
else
|
||||
m_pClient->m_pSounds->Stop(SOUND_MENU);
|
||||
m_NeedRestartSound = g_Config.m_SndEnable && (!s_SndEnable || s_SndRate != g_Config.m_SndRate);
|
||||
}
|
||||
CUIRect UseSoundButton;
|
||||
Sound.HSplitTop(ButtonHeight, &UseSoundButton, &Sound);
|
||||
|
||||
if(g_Config.m_SndEnable)
|
||||
{
|
||||
|
@ -1627,15 +1925,41 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
|
|||
g_Config.m_SndRate = 48000;
|
||||
}
|
||||
|
||||
m_NeedRestartSound = !s_SndEnable || s_SndRate != g_Config.m_SndRate;
|
||||
m_NeedRestartSound = g_Config.m_SndInit && (!s_SndInit || s_SndRate != g_Config.m_SndRate);
|
||||
}
|
||||
|
||||
Right.HSplitTop(ButtonHeight, &Button, &Right);
|
||||
DoScrollbarOption(&g_Config.m_SndVolume, &g_Config.m_SndVolume, &Button, Localize("Volume"), 110.0f, 0, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sound.HSplitTop(Spacing, 0, &Sound);
|
||||
Sound.HSplitTop(ButtonHeight, &Button, &Sound);
|
||||
Button.VSplitLeft(ButtonHeight, 0, &Button);
|
||||
static int s_ButtonInitSounds = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonInitSounds, Localize("Load the sound system"), g_Config.m_SndInit, &Button))
|
||||
{
|
||||
g_Config.m_SndInit ^= 1;
|
||||
m_NeedRestartSound = g_Config.m_SndInit && (!s_SndInit || s_SndRate != g_Config.m_SndRate);
|
||||
}
|
||||
}
|
||||
|
||||
static int s_ButtonSndEnable = 0;
|
||||
if(DoButton_CheckBox(&s_ButtonSndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &UseSoundButton))
|
||||
{
|
||||
g_Config.m_SndEnable ^= 1;
|
||||
if(g_Config.m_SndEnable)
|
||||
{
|
||||
g_Config.m_SndInit = 1;
|
||||
if(g_Config.m_SndMusic)
|
||||
m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
|
||||
}
|
||||
else
|
||||
m_pClient->m_pSounds->Stop(SOUND_MENU);
|
||||
}
|
||||
|
||||
// reset button
|
||||
MainView.HSplitBottom(60.0f, 0, &BottomView);
|
||||
BottomView.HSplitBottom(60.0f, 0, &BottomView);
|
||||
|
||||
Spacing = 3.0f;
|
||||
float ButtonWidth = (BottomView.w/6.0f)-(Spacing*5.0)/6.0f;
|
||||
|
@ -1649,6 +1973,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
|
|||
if(DoButton_Menu(&s_ResetButton, Localize("Reset"), 0, &Button))
|
||||
{
|
||||
g_Config.m_SndEnable = 1;
|
||||
g_Config.m_SndInit = 1;
|
||||
if(!g_Config.m_SndMusic)
|
||||
{
|
||||
g_Config.m_SndMusic = 1;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <generated/client_data.h>
|
||||
#include <game/client/gameclient.h>
|
||||
|
||||
#include "menus.h"
|
||||
#include "motd.h"
|
||||
|
||||
void CMotd::Clear()
|
||||
|
@ -18,6 +19,9 @@ void CMotd::Clear()
|
|||
|
||||
bool CMotd::IsActive()
|
||||
{
|
||||
// dont render modt if the menu is active
|
||||
if(m_pClient->m_pMenus->IsActive())
|
||||
return false;
|
||||
return time_get() < m_ServerMotdTime;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,11 @@ void CNamePlates::RenderNameplate(
|
|||
|
||||
|
||||
char aName[64];
|
||||
str_format(aName, sizeof(aName), "%2d: %s", ClientID, g_Config.m_ClShowsocial ? m_pClient->m_aClients[ClientID].m_aName: "");
|
||||
float tw = TextRender()->TextWidth(0, FontSize, aName, -1);
|
||||
str_format(aName, sizeof(aName), "%s", g_Config.m_ClShowsocial ? m_pClient->m_aClients[ClientID].m_aName: "");
|
||||
|
||||
CTextCursor Cursor;
|
||||
float tw = TextRender()->TextWidth(0, FontSize, aName, -1) + RenderTools()->GetClientIdRectSize(FontSize);
|
||||
TextRender()->SetCursor(&Cursor, Position.x-tw/2.0f, Position.y-FontSize-38.0f, FontSize, TEXTFLAG_RENDER);
|
||||
|
||||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.5f*a);
|
||||
TextRender()->TextColor(1.0f, 1.0f, 1.0f, a);
|
||||
|
@ -45,7 +48,16 @@ void CNamePlates::RenderNameplate(
|
|||
TextRender()->TextColor(0.7f, 0.7f, 1.0f, a);
|
||||
}
|
||||
|
||||
TextRender()->Text(0, Position.x-tw/2.0f, Position.y-FontSize-38.0f, FontSize, aName, -1);
|
||||
const vec4 IdTextColor(0.1f, 0.1f, 0.1f, a);
|
||||
vec4 BgIdColor(1.0f, 0.5f, 0.5f, a * 0.5f);
|
||||
if(m_pClient->m_aClients[ClientID].m_Team == TEAM_BLUE)
|
||||
BgIdColor = vec4(0.7f, 0.7f, 1.0f, a * 0.5f);
|
||||
|
||||
if(a > 0.001f)
|
||||
{
|
||||
RenderTools()->DrawClientID(TextRender(), &Cursor, ClientID, BgIdColor, IdTextColor);
|
||||
TextRender()->TextEx(&Cursor, aName, -1);
|
||||
}
|
||||
|
||||
TextRender()->TextColor(1,1,1,1);
|
||||
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
|
||||
|
|