/* * Descent 3 * Copyright (C) 2024 Parallax Software * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/editor/ScriptMassCompile.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003-08-26 03:57:39 $ * $Author: kevinb $ * * Implementation of mass script compile dialog * * $Log: not supported by cvs2svn $ * * 9 4/03/99 1:36a Jeff * added no-check out option for mass compiler * * 8 2/25/99 12:34p Jeff * don't display message if someone has a file checked out during mass * compile * * 7 2/21/99 8:05p Jeff * better handling of out-of-sync scripts * * 6 1/11/99 3:34p Jeff * added checks for when going editor->game to see if scripts are out of * date, if so give the option of breaking out. Add some options to mass * script compiler, along with a toolbar shortcut. * * 5 12/30/98 4:39p Jeff * selectable to what scripts to display (checked out, non-checked out or * both) * * 4 12/20/98 9:57p Jeff * finished mass compile dialog * * 3 12/18/98 12:36p Jeff * created a function to determine a script's type and hooked it in * * 2 12/18/98 12:11p Jeff * added mass script compile dialog * * $NoKeywords: $ */ // ScriptMassCompile.cpp : implementation file // #include "stdafx.h" #include "editor.h" #include "ScriptMassCompile.h" #include "cfile.h" #include "gamefile.h" #include "gamefilepage.h" #include "AppDatabase.h" #include "Descent.h" #include "mono.h" #include "ddio.h" #include "ScriptCompilerAPI.h" #include #include #include "mem.h" #include "pserror.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CScriptMassCompile dialog CString MassScriptEditContent; CEdit *MassScriptEdit; void writeline(char *format, ...); CScriptMassCompile::CScriptMassCompile(CWnd *pParent /*=NULL*/) : CDialog(CScriptMassCompile::IDD, pParent) { //{{AFX_DATA_INIT(CScriptMassCompile) m_AutoCheckIn = FALSE; m_DisplayType = 2; m_NoCheckout = FALSE; //}}AFX_DATA_INIT } void CScriptMassCompile::DoDataExchange(CDataExchange *pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CScriptMassCompile) DDX_Control(pDX, IDC_LIST, m_ScriptList); DDX_Check(pDX, IDC_AUTOCHECKIN, m_AutoCheckIn); DDX_Radio(pDX, IDC_LOCKED, m_DisplayType); DDX_Check(pDX, IDC_NOCHECKOUT, m_NoCheckout); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CScriptMassCompile, CDialog) //{{AFX_MSG_MAP(CScriptMassCompile) ON_BN_CLICKED(IDC_BUILD, OnBuild) ON_BN_CLICKED(IDC_LOCKED, OnLocked) ON_BN_CLICKED(IDC_NOTLOCKED, OnNotlocked) ON_BN_CLICKED(IDC_BOTH, OnBoth) ON_BN_CLICKED(IDC_SELECTALL, OnSelectall) ON_BN_CLICKED(IDC_OODSCRIPTS, OnOodscripts) ON_BN_CLICKED(IDC_OOSSCRIPTS, OnOosscripts) ON_BN_CLICKED(IDC_NOCHECKOUT, OnNocheckout) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CScriptMassCompile message handlers void CScriptMassCompile::OnBuild() { UpdateData(true); MassScriptEditContent = ""; writeline("Starting Mass Build."); int i, list_size, listbox_size, index; int *index_map = NULL; CCheckListBox *list; char tempbuffer[_MAX_PATH]; CWnd *wnd; list = (CCheckListBox *)GetDlgItem(IDC_LIST); listbox_size = list->GetCount(); list_size = 0; for (i = 0; i < listbox_size; i++) { if (list->GetCheck(i)) { list_size++; } } if (list_size == 0) return; index_map = mem_rmalloc(list_size); if (!index_map) return; index = 0; for (i = 0; i < listbox_size; i++) { if (list->GetCheck(i)) { index_map[index] = i; index++; } } wnd = (CWnd *)GetDlgItem(IDC_FILENAME); bool ret1, ret2, ret3, ret4; for (i = 0; i < list_size; i++) { index = index_map[i]; SetStepText(1, "-Not Done-"); SetStepText(2, "-Not Done-"); SetStepText(3, "-Not Done-"); SetStepText(4, "-Not Done-"); list->GetText(index, tempbuffer); wnd->SetWindowText(tempbuffer); writeline("------------------------------- %s --------------------------", tempbuffer); Descent->defer(); ret1 = Step1(tempbuffer); Descent->defer(); ret2 = Step2(tempbuffer); Descent->defer(); ret3 = Step3(tempbuffer, ret2); Descent->defer(); if (ret1) { ret4 = Step4(tempbuffer); Descent->defer(); } else { SetStepText(4, "Skipping due to results of Step 1"); writeline("Step 4: Skipped due to result of Step 1 (maybe already checked out)"); ret4 = true; } } OutrageMessageBox("Mass Compile Complete"); mem_free(index_map); } void CScriptMassCompile::OnOK() { UpdateData(true); Database->write("EditorScriptAutoCheckin", m_AutoCheckIn); CDialog::OnOK(); } void writeline(char *format, ...) { char buffer[2048]; va_list marker; va_start(marker, format); std::vsprintf(buffer, format, marker); va_end(marker); MassScriptEditContent += buffer; MassScriptEditContent += "\r\n"; MassScriptEdit->SetWindowText(MassScriptEditContent.GetBuffer(0)); Descent->defer(); int total_lines = MassScriptEdit->GetLineCount(); int curr_index = MassScriptEdit->GetFirstVisibleLine(); if ((total_lines - curr_index) > 16) { // we need to scroll down a line MassScriptEdit->LineScroll((total_lines - curr_index) - 16); } } uint8_t DetermineScriptType(char *filename) { CFILE *file; file = cfopen(filename, "rt"); if (!file) { return 255; } char buffer[4096]; bool done = false; uint8_t script_type = ST_GAME; cf_ReadString(buffer, 4096, file); while (!(cfeof(file) || done)) { if (strstr(buffer, "GetTriggerScriptID")) { // we found it! script_type = ST_LEVEL; done = true; } cf_ReadString(buffer, 4096, file); } cfclose(file); return script_type; } void CScriptMassCompile::BuildList(void) { CCheckListBox *list = (CCheckListBox *)GetDlgItem(IDC_LIST); if (!list) return; list->ResetContent(); char buffer[_MAX_PATH]; int length; for (int i = 0; i < MAX_GAMEFILES; i++) { if (Gamefiles[i].used) { // we're only adding .cpp's to this list length = strlen(Gamefiles[i].name); if (length > 4 && !stricmp(&Gamefiles[i].name[length - 4], ".cpp")) { switch (m_DisplayType) { case 0: // checked out only { if (mng_FindTrackLock(Gamefiles[i].name, PAGETYPE_GAMEFILE) != -1) { strcpy(buffer, Gamefiles[i].name); buffer[length - 4] = '\0'; list->AddString(buffer); } } break; case 1: // non-check out only { if (mng_FindTrackLock(Gamefiles[i].name, PAGETYPE_GAMEFILE) == -1) { strcpy(buffer, Gamefiles[i].name); buffer[length - 4] = '\0'; list->AddString(buffer); } } break; case 2: // both { strcpy(buffer, Gamefiles[i].name); buffer[length - 4] = '\0'; list->AddString(buffer); } break; }; } } } } BOOL CScriptMassCompile::OnInitDialog() { CDialog::OnInitDialog(); bool bval; if (Database->read("EditorScriptAutoCheckin", &bval)) m_AutoCheckIn = bval; else m_AutoCheckIn = true; UpdateData(false); MassScriptEditContent = ""; MassScriptEdit = (CEdit *)GetDlgItem(IDC_OUTPUT); writeline("System Initialized."); if (!Network_up) { writeline("WARNING: You did not say yes to the data update, therefore, your work will not be saved for the scripts " "that you don't currently have checked out."); } writeline("----------------------------------------------------------------------------------------------------------" "--------------------------------------"); BuildList(); return TRUE; } void CScriptMassCompile::SetStepText(int step, char *format, ...) { if (step < 1 || step > 4) return; char buffer[1024]; va_list marker; va_start(marker, format); std::vsprintf(buffer, format, marker); va_end(marker); CWnd *wnd; int msg_to; switch (step) { case 1: wnd = (CWnd *)GetDlgItem(IDC_STEP1); msg_to = IDC_STEP1; break; case 2: wnd = (CWnd *)GetDlgItem(IDC_STEP2); msg_to = IDC_STEP2; break; case 3: wnd = (CWnd *)GetDlgItem(IDC_STEP3); msg_to = IDC_STEP3; break; case 4: wnd = (CWnd *)GetDlgItem(IDC_STEP4); msg_to = IDC_STEP4; break; }; wnd->SetWindowText(buffer); SendDlgItemMessage(msg_to, WM_PAINT, 0, 0); Descent->defer(); } // return true if the file was checked out for this step bool CheckOutGamefile(char *tempbuffer, bool show_ok_confirmation, bool report_who_has_locked); bool CScriptMassCompile::Step1(char *filename) { if (!Network_up) { SetStepText(1, "Skipping, Network 'Down'"); writeline("Step 1: Skipping, Due to the NO on data update"); return false; } if (m_NoCheckout) { SetStepText(1, "Skipping, 'no checkout' option checked"); writeline("Step 1: Skipping, 'no checkout' option checked"); return false; } char source_filename[_MAX_PATH], compiled_filename[_MAX_PATH]; // make the locker if (!mng_MakeLocker()) { SetStepText(1, "Unable to create locker, can't check out"); writeline("Step 1: Can't make locker file, skipping check out"); return false; } // make real filenames strcpy(source_filename, filename); strcpy(compiled_filename, filename); strcat(source_filename, ".cpp"); strcat(compiled_filename, ".dll"); bool found_script = false, found_compiled = false; int i; // make sure the compiled script is in the gamefiles for (i = 0; i < MAX_GAMEFILES; i++) { if (Gamefiles[i].used) { if (!found_script && !stricmp(Gamefiles[i].name, source_filename)) found_script = true; if (!found_compiled && !stricmp(Gamefiles[i].name, compiled_filename)) found_compiled = true; } if (found_script && found_compiled) break; } if (!found_script) { // ummm, this shouldn't happen MessageBox("Hmmm, I couldn't find the source file for the script in the manage system...this isn't good", "Uh oh"); SetStepText(1, "File Not Found"); writeline("Step 1: Couldn't find source script in manage system"); mng_EraseLocker(); return false; } bool ntco_script = true, ntco_compiled = true; if (!found_compiled) ntco_compiled = false; // see if we have these checked out if (mng_FindTrackLock(source_filename, PAGETYPE_GAMEFILE) != -1) ntco_script = false; if (ntco_compiled && mng_FindTrackLock(compiled_filename, PAGETYPE_GAMEFILE) != -1) ntco_compiled = false; // ok, we know what files we need to check out bool sret = false, cret = false; if (ntco_script) { writeline("Step 1: Checking out %s", source_filename); sret = CheckOutGamefile(source_filename, false, false); if (!sret) writeline("Step 1: Unable to check out %s", source_filename); } if (ntco_compiled) { writeline("Step 1: Checking out %s", compiled_filename); cret = CheckOutGamefile(compiled_filename, false, false); if (!cret) writeline("Step 1: Unable to check out %s", compiled_filename); } if ((ntco_script || ntco_compiled)) { if (((!ntco_script) || sret) && ((!ntco_compiled) || cret)) { SetStepText(1, "Files checked out"); writeline("Step 1: Success"); } else { SetStepText(1, "Error checking files out"); writeline("Step 1: Errors have occurred"); } } else { SetStepText(1, "No files needed to be checked out"); writeline("Step 1: Success"); } mng_EraseLocker(); return (sret || cret); } // return true if it's a level script bool CScriptMassCompile::Step2(char *filename) { char source_filename[_MAX_PATH]; strcpy(source_filename, filename); strcat(source_filename, ".cpp"); if (DetermineScriptType(source_filename) == ST_LEVEL) { writeline("Step 2: Determined to be a level script"); SetStepText(2, "Level Script"); return true; } else { writeline("Step 2: Determined to be a game script"); SetStepText(2, "Game Script"); return false; } return false; } void masscompilercallback(char *str) { MassScriptEditContent += str; MassScriptEdit->SetWindowText(MassScriptEditContent.GetBuffer(0)); int total_lines = MassScriptEdit->GetLineCount(); int curr_index = MassScriptEdit->GetFirstVisibleLine(); if ((total_lines - curr_index) > 16) { // we need to scroll down a line MassScriptEdit->LineScroll((total_lines - curr_index) - 16); } Descent->defer(); } bool CScriptMassCompile::Step3(char *filename, bool islevel) { tCompilerInfo ci; ci.callback = masscompilercallback; ci.script_type = (islevel) ? ST_LEVEL : ST_GAME; strcpy(ci.source_filename, filename); strcat(ci.source_filename, ".cpp"); char compiled_filename[_MAX_PATH], full_path[_MAX_PATH]; strcpy(compiled_filename, filename); strcat(compiled_filename, ".dll"); ddio_MakePath(full_path, LocalScriptDir, compiled_filename, NULL); if (cfexist(full_path)) { ddio_DeleteFile(full_path); } writeline("===START COMPILE==="); ScriptCompile(&ci); writeline(""); writeline("===END COMPILE==="); bool ret; if (cfexist(full_path)) { writeline("Step 3: DLL Created"); SetStepText(3, "DLL Created"); ret = true; } else { writeline("Step 3: DLL Not Created"); SetStepText(3, "DLL NOT Created"); ret = false; } return ret; } bool CheckInGamefile(char *tempbuffer, bool giveok); bool AddNewGameFile(char *fullpath, char *directory); bool CScriptMassCompile::Step4(char *filename) { if (!Network_up) { SetStepText(4, "Skipping, Network 'Down'"); writeline("Step 4: Skipping, Due to the NO on data update"); return false; } if (!m_AutoCheckIn) { SetStepText(4, "Skipping, Auto Checkin box not set"); writeline("Step 4: Skipping, Auto Checkin box not set"); return false; } char source_filename[_MAX_PATH], compiled_filename[_MAX_PATH]; // make the locker if (!mng_MakeLocker()) { SetStepText(4, "Unable to create locker, can't check in"); writeline("Step 4: Can't make locker file, skipping check in"); return false; } // make real filenames strcpy(source_filename, filename); strcpy(compiled_filename, filename); strcat(source_filename, ".cpp"); strcat(compiled_filename, ".dll"); bool ntci_source = false, ntci_compiled = false; int i; for (i = 0; i < MAX_GAMEFILES; i++) { if (Gamefiles[i].used) { if (!ntci_source && !stricmp(Gamefiles[i].name, source_filename) && (mng_FindTrackLock(source_filename, PAGETYPE_GAMEFILE) != -1)) { ntci_source = true; } if (!ntci_compiled && !stricmp(Gamefiles[i].name, compiled_filename) && (mng_FindTrackLock(source_filename, PAGETYPE_GAMEFILE) != -1)) { ntci_compiled = true; } } if (ntci_source && ntci_compiled) break; } if (!ntci_source && !ntci_compiled) { SetStepText(4, "Skipping, files not checked out"); writeline("Step 4: Skipping because both source and compiled are not checked out or not in the manage system"); mng_EraseLocker(); return false; } // check to make sure the compiled version exists if (!cfexist(compiled_filename)) { writeline("Step 4: %s does not exist...possibly due to compilation errors", compiled_filename); writeline("Step 4: Aborting check in"); SetStepText(4, "Aborted"); mng_EraseLocker(); return false; } // see if we need to add the compiled version to manage system if (!ntci_compiled) { int j; for (j = 0; j < MAX_GAMEFILES; j++) { if (Gamefiles[j].used) { if (!stricmp(Gamefiles[j].name, compiled_filename)) break; } } if (j >= MAX_GAMEFILES) { // compiled file doesn't exist, we'll need to add it writeline("Step 4: Attempting to add %s to manage system", compiled_filename); char fullpath[_MAX_PATH]; ddio_MakePath(fullpath, LocalScriptDir, compiled_filename, NULL); bool ret = AddNewGameFile(fullpath, "scripts"); if (!ret) { writeline("Step 4: Unable to add %s to manage system", compiled_filename); writeline("Step 4: Aborting"); SetStepText(4, "Aborted"); mng_EraseLocker(); return false; } else ntci_compiled = true; } } // we have at least 1 file to check in bool sret = true, cret = true; if (ntci_source) { sret = CheckInGamefile(source_filename, false); if (!sret) { writeline("Step 4: Unable to check in source file"); } } if (ntci_compiled) { cret = CheckInGamefile(compiled_filename, false); if (!cret) { writeline("Step 4: Unable to check in compiled file"); } } if (!sret || !cret) { SetStepText(4, "There were errors checking in files"); writeline("Step 4: Errors had occurred"); } else { SetStepText(4, "Success"); writeline("Step 4: Success"); } mng_EraseLocker(); return (sret || cret); } void CScriptMassCompile::OnLocked() { UpdateData(true); BuildList(); } void CScriptMassCompile::OnNotlocked() { UpdateData(true); BuildList(); } void CScriptMassCompile::OnBoth() { UpdateData(true); BuildList(); } void CScriptMassCompile::OnSelectall() { CCheckListBox *list = (CCheckListBox *)GetDlgItem(IDC_LIST); if (!list) return; int count = list->GetCount(); for (int i = 0; i < count; i++) { list->SetCheck(i, 1); list->SetSel(i, TRUE); } } bool IsScriptOutofDate(char *name); void CScriptMassCompile::OnOodscripts() { CCheckListBox *list = (CCheckListBox *)GetDlgItem(IDC_LIST); if (!list) return; char old_dir[_MAX_PATH]; ddio_GetWorkingDir(old_dir, _MAX_PATH); ddio_SetWorkingDir(LocalScriptDir); char filename[_MAX_PATH]; int count = list->GetCount(); for (int i = 0; i < count; i++) { list->GetText(i, filename); strcat(filename, ".cpp"); if (IsScriptOutofDate(filename)) { list->SetCheck(i, 1); list->SetSel(i, TRUE); } else { list->SetCheck(i, 0); list->SetSel(i, FALSE); } } ddio_SetWorkingDir(old_dir); } bool IsScriptOutofSync(char *name); void CScriptMassCompile::OnOosscripts() { CCheckListBox *list = (CCheckListBox *)GetDlgItem(IDC_LIST); if (!list) return; char filename[_MAX_PATH]; int count = list->GetCount(); for (int i = 0; i < count; i++) { list->GetText(i, filename); strcat(filename, ".cpp"); if (IsScriptOutofSync(filename)) { list->SetCheck(i, 1); list->SetSel(i, TRUE); } else { list->SetCheck(i, 0); list->SetSel(i, FALSE); } } } void CScriptMassCompile::OnNocheckout() { // TODO: Add your control notification handler code here }