Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions assets/data0_21pure/ui/porkui/css/workshop.rcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* The mod list occupies the scrollable upper portion of #leftside.
#content is 636dp tall; leave ~280dp for the fixed submit panel. */
#leftside {
height: 340dp;
overflow-y: auto;
}

#workshop-list {
width: 100%;
height: 100%;
}

#workshop-installed-grid {
width: 100%;
}

#workshop-installed-grid datagridcolumn {
background-color: #1e1a28;
color: #99ccff;
padding: 6dp 8dp;
font-weight: bold;
}

#workshop-installed-grid datagridrow {
background-color: #141219;
border-bottom: 1dp #272134;
}

#workshop-installed-grid datagridrow:hover {
background-color: #1e1a28;
}

#workshop-installed-grid datagridcell {
padding: 6dp 8dp;
color: #ffffff;
}

/* Publish panel — floats above the footer, fixed to the bottom-left */
#workshop-submit {
position: fixed;
bottom: 18dp;
left: 0dp;
width: 75%;
z-index: 4;
padding: 0dp 16dp 8dp 16dp;
}

#workshop-submit .dropshadow {
padding: 10dp 14dp;
}

.workshop-help {
margin-bottom: 6dp;
color: #b9c7d6;
}


.required {
color: #eb8c8a;
font-weight: bold;
}
9 changes: 8 additions & 1 deletion assets/data0_21pure/ui/porkui/template.rml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@
}
}

body.getElementById( 'version_str' ).setInnerRML( "Warfork (Steam Release)" );
body.getElementById( 'version_str' ).setInnerRML( "Warfork (Steam Release)" );

/* hide the workshop tab when Steam is unavailable */
Element @workshopLink = body.getElementById( 'link_workshop' );
if( @workshopLink != null && !game.steamAvaliable() ) {
workshopLink.css( 'display', 'none' );
}

/* grab the navigation panel */
@navi = body.getElementById( 'navi' );
Expand Down Expand Up @@ -190,6 +196,7 @@
<a href="index.rml" id="link_profile">Home</a>
<a href="#" id="link_game" onclick="$openTutorialDialog">Play</a>
<!-- <a href="chat.rml" id="link_chat">Chat</a> -->
<a href="workshop.rml" id="link_workshop">Workshop</a>
<a href="options.rml" id="link_options">Options</a>
<a href="credits.rml" id="link_credits">Credits</a>
<a href="#" id="link_quit" onclick="OpenQuitDialog();">Quit</a>
Expand Down
157 changes: 157 additions & 0 deletions assets/data0_21pure/ui/porkui/workshop.rml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<rml>
<head>
<title>workshop</title>
<link type="text/template" href="template.rml" />
<link rel="stylesheet" type="text/css" href="css/workshop.rcss" />
<script>
ElementFormControl @modSelect;
ElementFormControl @titleInput;
ElementFormControl @descriptionInput;
ElementFormControl @tagsInput;
ElementFormControl @visibilityInput;
ElementFormControl @changeNoteInput;

void populateModSelect( Element @body )
{
Element @sel = body.getElementById( 'workshop-mod-select' );
if( @sel == null ) return;

String mods = game.workshopLocalMods();
String rml = '';
if( mods == '' ) {
rml = '<option value="-1">No local mods found</option>';
} else {
uint pos = 0;
while( pos < mods.len() ) {
uint nl = mods.locate( "\n", pos );
if( nl == mods.len() ) nl = mods.len();
String line = mods.substr( pos, nl - pos );
pos = nl + 1;
if( line == '' ) continue;
uint tab = line.locate( "\t", 0 );
if( tab == line.len() ) continue;
String name = line.substr( 0, tab );
String index = line.substr( tab + 1, line.len() - tab - 1 );
rml += '<option value="' + index + '">' + name + '</option>';
}
if( rml == '' ) rml = '<option value="-1">No local mods found</option>';
}
sel.setInnerRML( rml );
}

void onWorkshopLoad( Element @body, Event @evt )
{
onTemplateLoad( body, evt );

@modSelect = cast<ElementFormControl>( body.getElementById( 'workshop-mod-select' ) );
@titleInput = cast<ElementFormControl>( body.getElementById( 'workshop-title' ) );
@descriptionInput = cast<ElementFormControl>( body.getElementById( 'workshop-description' ) );
@tagsInput = cast<ElementFormControl>( body.getElementById( 'workshop-tags' ) );
@visibilityInput = cast<ElementFormControl>( body.getElementById( 'workshop-visibility' ) );
@changeNoteInput = cast<ElementFormControl>( body.getElementById( 'workshop-change-note' ) );

populateModSelect( body );
}

void onWorkshopShow( Element @body, Event @evt )
{
onTemplateShow( body, evt );
animationsOnShow();
game.workshopRefresh();
populateModSelect( body );
}

void onWorkshopSubmit( Element @elem, Event @evt )
{
if( @modSelect == null || @titleInput == null || @visibilityInput == null ) {
return;
}

int modIndex = modSelect.value.toInt();
if( modIndex == -1 ) {
notificationPopup( 'Please select a mod folder.', true );
return;
}
if( titleInput.value.trim() == '' ) {
notificationPopup( 'Title is required.', true );
return;
}

String result = game.workshopSubmitMap(
modIndex,
titleInput.value,
@descriptionInput != null ? descriptionInput.value : '',
@tagsInput != null ? tagsInput.value : '',
visibilityInput.value,
@changeNoteInput != null ? changeNoteInput.value : ''
);

String lowerResult = result.tolower();
bool isError = lowerResult.locate( 'failed', 0 ) != lowerResult.len()
|| lowerResult.locate( 'required', 0 ) != lowerResult.len()
|| lowerResult.locate( 'unavailable', 0 ) != lowerResult.len()
|| lowerResult.locate( 'invalid', 0 ) != lowerResult.len()
|| lowerResult.locate( 'too many', 0 ) != lowerResult.len();

notificationPopup( result, isError );
if( !isError ) {
game.workshopRefresh();
}
}
</script>
</head>
<body template="porkui" onload="$onWorkshopLoad" onshow="$onWorkshopShow">

<div id="leftside">
<div id="workshop-list">
<datagrid id="workshop-installed-grid" source="workshop.installed">
<col fields="display_name" width="35%">Mod</col>
<col fields="tags" width="20%">Tags</col>
<col fields="is_installed" width="12%">Installed</col>
<col fields="is_local" width="12%">Uploaded</col>
<col fields="score" width="10%">Score</col>
<col fields="votes_up" width="10%">+</col>
</datagrid>
</div>
</div>

<div id="sidebar">
<div id="sidebar2">
<button onclick="game.workshopRefresh();">Refresh</button>
</div>
</div>

<div id="workshop-submit">
<div class="dropshadow">
<p class="workshop-help">Publish a local mod to Steam Workshop. Place your mod folder in <em>mods/</em> and add a <em>preview.png</em> for a thumbnail.</p>
<br/>
<div class="title">Mod folder</div>
<select id="workshop-mod-select"></select>
<br/>
<div class="title">Title <span class="required">*</span></div>
<input id="workshop-title" class="text" type="text" />
<br/>
<div class="title">Description</div>
<input id="workshop-description" class="text" type="text" placeholder="Short description of your mod" />
<br/>
<div class="title">Tags</div>
<input id="workshop-tags" class="text" type="text" value="map" placeholder="e.g. map, weapon" />
<br/>
<hr class="nicehr"/>
<div class="title">Visibility</div>
<select id="workshop-visibility">
<option value="private" selected>Private</option>
<option value="friends">Friends only</option>
<option value="public">Public</option>
</select>
<br/>
<div class="title">Change note</div>
<input id="workshop-change-note" class="text" type="text" value="Initial upload" />
<br/>
<br/>
<button class="button-apply" onclick="$onWorkshopSubmit">Publish to Workshop</button>
</div>
</div>

</body>
</rml>
2 changes: 1 addition & 1 deletion source/client/cl_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2308,7 +2308,7 @@ static void CL_InitLocal( void )
if ( !CL_IsNameValid(name->string) ){
if ( STEAMSHIM_active() ){
struct steam_rpc_shim_common_s request;
request.cmd = RPC_REQUEST_STEAM_ID;
request.cmd = RPC_PERSONA_NAME;
STEAMSHIM_sendRPC( &request, sizeof( struct steam_rpc_shim_common_s ), name, CL_RPC_cb_persona, &syncIndex );
} else {
Cvar_Set( name->name, CL_RandomName() );
Expand Down
3 changes: 3 additions & 0 deletions source/qcommon/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include "crashpad.h"

#define STB_DS_IMPLEMENTATION 1
#include "../extern/stb/stb_ds.h"

#define MAX_NUM_ARGVS 50

static bool dynvars_initialized = false;
Expand Down
60 changes: 53 additions & 7 deletions source/qcommon/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../qalgo/md5.h"
#include "../qalgo/q_trie.h"
#include "../gameshared/q_sds.h"

#include "../extern/stb/stb_ds.h"
/*
=============================================================================

Expand Down Expand Up @@ -182,6 +182,8 @@ static searchpath_t *fs_root_searchpath; // base path directory
static searchpath_t *fs_write_searchpath; // write directory
static searchpath_t *fs_downloads_searchpath; // write directory for downloads from game servers

static searchpath_t *fs_base_mod_paths = NULL;

static mempool_t *fs_mempool;

#define FS_Malloc( size ) Mem_Alloc( fs_mempool, size )
Expand Down Expand Up @@ -4111,13 +4113,26 @@ bool FS_SetGameDirectory( const char *dir, bool force )
return true;
}

/*
* FS_AddBasePath
*/
static searchpath_t* FS_AddSearchPath(searchpath_t* base, const char *path, bool append_basegame) {
assert(base);
assert(base->next);

searchpath_t *newpath = ( searchpath_t* )FS_Malloc( sizeof( searchpath_t ) );
newpath->base = base;
newpath->next = base->next;
base->next = newpath;
if(newpath->next) {
newpath->next->base = newpath;
}
newpath->path = FS_CopyString( path );
newpath->append_basegame = append_basegame;
COM_SanitizeFilePath( newpath->path );
return newpath;
}

static void FS_AddBasePath( const char *path, bool append_basegame )
{
searchpath_t *newpath;

newpath = ( searchpath_t* )FS_Malloc( sizeof( searchpath_t ) );
newpath->path = FS_CopyString( path );
newpath->next = fs_basepaths;
Expand All @@ -4131,10 +4146,39 @@ void FS_AddExtraPK3Directory( const char *path )
FS_AddBasePath( path, false );
}

void FS_UnRegisterModPath( searchpath_t *search_path )
{
QMutex_Lock( fs_searchpaths_mutex );
searchpath_t* last_path = fs_basepaths;
for( searchpath_t *p = fs_basepaths; p != NULL; p = p->next ) {
if(p == search_path) {
last_path->next = p->next;
FS_Free( p->path );
FS_Free( p);
break;
}
last_path = p;
}
QMutex_Unlock( fs_searchpaths_mutex );
}

searchpath_t* FS_RegisterModPath( const char *path )
{
QMutex_Lock( fs_searchpaths_mutex );
searchpath_t *newpath = ( searchpath_t* )FS_Malloc( sizeof( searchpath_t ) );
newpath->path = FS_CopyString( path );
newpath->pack = NULL;
newpath->next = fs_base_mod_paths->next;
newpath->append_basegame = false;
fs_base_mod_paths->next = newpath;
COM_SanitizeFilePath( newpath->path );
QMutex_Unlock( fs_searchpaths_mutex );
return newpath;
}

/*
* FS_FreeSearchFiles
*/
* FS_FreeSearchFiles
*/
static void FS_FreeSearchFiles( void )
{
int i;
Expand Down Expand Up @@ -4348,6 +4392,7 @@ void FS_Init( void )
fs_numsearchfiles = FS_MIN_SEARCHFILES;
fs_searchfiles = ( searchfile_t* )FS_Malloc( sizeof( searchfile_t ) * fs_numsearchfiles );


memset( fs_filehandles, 0, sizeof( fs_filehandles ) );

//
Expand Down Expand Up @@ -4385,6 +4430,7 @@ void FS_Init( void )
FS_AddBasePath( downloadsdir, true );
fs_downloads_searchpath = fs_basepaths;
}
fs_base_mod_paths = fs_basepaths;

if( fs_cdpath->string[0] )
FS_AddBasePath( fs_cdpath->string, true );
Expand Down
Loading