Export'lar ve state bag'ler
İki giriş yolu var ve ucuz olanı önce.
phoneapi <id>, sunucu konsolunda bir oyuncu için aşağıdaki her şeyi yazdırır. Buradaki bir şey beklediğiniz yanıtı vermiyorsa, daha fazla okumadan önce bunu çalıştırın — hangi tarafın yanlış olduğunu tahmin etmekten daha hızlıdır.
State bag’ler — hiçbir şeye mal olmayan yanıtlar
Section titled “State bag’ler — hiçbir şeye mal olmayan yanıtlar”Bir state bag için callback, olay veya bu kaynakla bir anlaşma gerekmez. Soran her makinede okunan bir tablodur, altınızda bu kaynak yeniden başlatılsa bile hayatta kalır ve client’ta da server’da da aynı şekilde çalışır.
-- serverif Player(src).state.onCallWith then ... end
-- client, about somebody elseif Player(GetPlayerFromServerId(id)).state.phoneOpen then ... end| Bag | Tür | |
|---|---|---|
phoneNumber | string | taşıdıkları telefonun numarası |
phoneName | string | o telefon birini aradığında gösterdiği ad |
phoneDevice | string | nil | eşya modunda bunun hangi telefon eşyası olduğu. Telefonlar karakterlere aitken nil |
phoneOpen | boolean | telefon dışarıda ve ekranda |
onCallWith | number | nil | hattın diğer ucundaki source |
callAnswered | boolean | biri açtı. Hâlâ çalıyorken false |
speakerphone | boolean | |
mutedCall | boolean | kendilerini sessize aldılar |
otherMutedCall | boolean | diğer uç kendini sessize aldı |
flashlight | boolean | el fenerleri açık. Her client ışını o ped üzerinde çizer |
phoneCamera | boolean | bir vizör açık: bir fotoğraf çekmek üzereler |
phoneSignal | number | kaç çubuk, 0 ile Config.Signal.Bars arası. 0, şehrin ulaşamadığı bir telefon demektir |
Bilmeye değer üç şey:
Sunucu tarafından yazılırlar. Client de hepsini bilir ve daha az satırla yayınlayabilirdi, ancak bir client hepsi hakkında yalan söyleyebilir ve bir anticheat’in okuduğu bir bag’in okunmaya değer olması gerekir.
Çalmak, bir aramada olmak sayılır. onCallWith, bir telefon çaldığı anda ayarlanır, çünkü hat meşguldür — henüz doğru olmayan şey, birinin açmış olmasıdır ve bu callAnswered’dır.
onCallWith, gerçek bir arama sırasında nil olabilir. Diğer uç, şehirdeki bir oyuncu yerine birinin tarayıcısı olabilir. callAnswered yine true’dur; yalnızca adı verilecek bir source yoktur.
El feneri gerçekten bir şeyi aydınlatana kadar bir flashlight bag’i yoktu; gerekçe, her zaman false olan bir bag’in hiç olmayan bir bag’den daha kötü olduğuydu — biri eksik bir özelliktir, diğeri yanlış bir yanıt. Artık bir şeyi aydınlatıyor, dolayısıyla yayınlanıyor.
Sunucu export’ları
Section titled “Sunucu export’ları”exports.mic_phone:GetNumber(src) --> '555-010-2048'exports.mic_phone:GetName(src) --> 'Jean Dupont'exports.mic_phone:GetIdentifier(src) --> 'char1:abc…' or 'device:abc…' in item modeexports.mic_phone:GetDevice(src) --> the phone item's id, or nilexports.mic_phone:HasPhone(src) --> are they carrying one at allexports.mic_phone:IsOpen(src)exports.mic_phone:IsInCall(src)exports.mic_phone:CallWith(src) --> the other source, or nil
exports.mic_phone:GetSource(number) --> src, for a numberexports.mic_phone:NumberOf(identifier) --> works for somebody who is not onlineexports.mic_phone:IdentifierOf(number)
exports.mic_phone:Call(src, number) --> rings it from their phone, exactly as dialling wouldexports.mic_phone:EndCall(src)exports.mic_phone:AddContact(src, name, number, { email =, notes =, favorite = })exports.mic_phone:RemoveContact(src, number)exports.mic_phone:SendNotification(src, { app =, title =, body = })exports.mic_phone:OpenApp(src, 'messages')exports.mic_phone:OpenPhone(src) / ClosePhone(src)
exports.mic_phone:SendMessage(number, text, from)exports.mic_phone:SendMail(identifierOrNumber, fromName, fromAddress, subject, body)exports.mic_phone:SendInvoice(senderSrc, targetNumber, label, amount, society)Call, telefonun kendisine söylenecek olanı döndürür — { ok = false, reason = 'busy' }, 'airplane', 'unknown', 'offline' — çünkü telefonun kendi arama tuşlarının çalıştırdığı aynı işleyiciyi çalıştırır. Yanlış yapılabilecek tek bir kod yolu ve tek bir kurallar kümesi vardır.
Yanıtı nil olan bir export hiç değer döndürmez; nil bir değer değil. Doğrudan bir argüman listesine konduğunda "nil" olmaz — listeyi kısaltır. Önce bir yerel değişkene koyun:
local with = exports.mic_phone:CallWith(src) -- and not print(exports.mic_phone:CallWith(src), x)Telefonun kendisi
Section titled “Telefonun kendisi”Başka bir kaynağın kendi başına yanıtlamak zorunda kaldığı sorular. Her biri telefonun zaten yaptığı bir aramadır; dolayısıyla yanlış yapılabilecek tek bir kod yolu ve tek bir kurallar kümesi vardır.
exports.mic_phone:GetBattery(src) --> 0-100, or nil when this city has no battery at allexports.mic_phone:SetBattery(src, 40) --> your own charger, or a story that drains oneexports.mic_phone:IsCharging(src)exports.mic_phone:HasAirplaneMode(src) --> the city cannot reach them; their own phone still works
exports.mic_phone:GetSignal(src) --> 0 to Config.Signal.Bars. Also the `phoneSignal` state bagexports.mic_phone:SetJammed(src, true) --> takes their bars away: a heist, a prison, a story
exports.mic_phone:GetGallery(src) --> every picture: { id, url, width, height, kind, created }exports.mic_phone:AddPhoto(src, url, w, h) --> puts one in it, and it appears without a rebootexports.mic_phone:GetContacts(src)
exports.mic_phone:GetInvoices(src) --> every invoice on that phone, paid and unpaidexports.mic_phone:UnpaidInvoices(src) --> count, total
exports.mic_phone:SendLocation(number, x, y, 'The docks', from) --> a map pin in a conversation
exports.mic_phone:GetSocialHandle(src, 'instapic') --> 'nightshift', or nil if they never signed upexports.mic_phone:SocialPost(src, 'twixel', { text = 'Anybody seen a blue Sultan?' })exports.mic_phone:SetVerified(src, 'twixel', true) --> the tick beside their name, per app
exports.mic_phone:GetRadioChannel(src) --> 12, or nilexports.mic_phone:SetRadioChannel(src, 12) --> 0 takes them off itGetBattery’nin nil yanıtı vermesi, 0 yanıtı vermesiyle aynı şey değildir: nil, bu sunucunun bataryayı hiç açmadığı anlamına gelir. İkisini aynı sayan bir script, telefonun asla bitmediği bir şehirde birinin ambulans çağırmasını engeller.
AddPhoto, URL’yi bu sunucunun izin verdiği host’lara karşı kontrol eder; tıpkı kameranın çektiği bir fotoğrafın kontrol edilmesi gibi. Herhangi bir adresi gösterecek bir galeri, birinin her şeye yönlendirebileceği bir galeridir.
SocialPost ve SetRadioChannel, telefonun kendi işleyicilerini çalıştırır; dolayısıyla ekranın uyduğu şeylere uyarlar: o uygulamada hesap yoksa gönderi yoktur ve bu mesleğin sahip olamayacağı bir kanal burada da reddedilir.
Piyasa
Section titled “Piyasa”Altı coin; fiyatları, bir client’tan kimsenin erişemeyeceği bir zamanlayıcıyla sunucu tarafından belirlenir. Aşağıdaki her şey coin ve para cinsindendir — asla kaynağın saydığı milyonda birlik birimlerle değil — dolayısıyla birine bir şeyin dörtte birini ödeyen bir script 0.25 der.
exports.mic_phone:Coins() --> every coin: id, name, symbol, price, change, window, historyexports.mic_phone:CoinPrice('santo') --> 42137.55, in money. nil when there is no such coinexports.mic_phone:GetCrypto(src, 'santo') --> 0.4218exports.mic_phone:GetCryptoValue(src) --> what their whole portfolio is worth, in money
exports.mic_phone:AddCrypto(src, 'omen', 12.5) --> true when it landedexports.mic_phone:RemoveCrypto(src, 'omen', 12.5) --> false when they did not have it, and nothing movesexports.mic_phone:SetCoinPrice('omen', 0.4) --> move the market for a storyRemoveCrypto, negatife düşmek yerine reddeder; dolayısıyla yanıtı aynı zamanda “ödeyebildi mi” sorusunun yanıtıdır — coin karşılığı bir şey satan bir mağazanın gerçekten sormak istediği budur:
if exports.mic_phone:RemoveCrypto(src, 'omen', price) then giveThem(thing) endCüzdan karaktere veya telefona aittir ve bu Config.Apps.Crypto.Wallet ayarıdır. Cihaz modunda bir telefonu çalmak portföyü de beraberinde çalar; karakter modunda çalınan bir telefon hırsıza boş bir uygulama gösterir. Export’lar her iki durumda da bir source alır ve hangisi olduğunu bilmeleri gerekmez.
Konsoldaki phonecrypto piyasayı yazdırır, phonecrypto <id> o oyuncunun neye sahip olduğunu yazdırır ve phonecrypto price <coin> <money> fiyatı elle oynatır.
Batarya ve el feneri
Section titled “Batarya ve el feneri”İkisi de config’den açılır veya kapatılır — shared/config/battery.lua ve Config.Flashlight — ve ikisi de varsayılan olarak batarya için kapalı, el feneri için açıktır.
exports.mic_phone:BatteryLevel(src) --> 0-100, or 100 when the battery is switched offexports.mic_phone:IsPhoneCharging(src)exports.mic_phone:ChargePhone(src, true) -- plug in; false unplugsBir şarj aleti cepteki bir eşya olmak zorunda değildir. Config.Battery.Charger.Item kutudan çıktığı gibi size bir tane verir ve ChargePhone diğer her şey içindir: bir arabadaki kablo, duvardaki bir priz, bir masanın arkasındaki bir prop.
phonebattery [charge|unplug|full|empty] <id> onu oynatır; bu, sabrınızı test etmeden bir bataryayı test etmenin yoludur.
Yönetici komutları
Section titled “Yönetici komutları”Oyundaki yöneticilerin (ve konsolun) bir şeyin neden istediğiniz gibi çalışmadığını bulmak için birkaç komutu vardır. Yalnızca bakarlar ya da bir oyuncunun telefonunu bilerek değiştirirler; hiçbiri bir şey uydurmaz.
phoneapi <id> | bir oyuncu için state bag’ler, export’lar ve batarya |
phoneapps | config’in çözümlediği haliyle uygulama listesi |
phonedevice [backup|restore] <id> | hangi telefonu tuttukları ve sakladıkları kopyalar |
phonebattery [charge|unplug|full|empty] <id> |
phoneapi ayrıca o telefonda sinyal olup olmadığını ve onun için neyin bekletildiğini de yazdırır; bu, “sinyal yok”tan “bildirim geldi”ye giden zinciri iki satırda verir. Dört yerden geçer ve hangisinin yanlış gittiğini görmenin bir yolu yoktu.
Seviye bir zamanlayıcı değildir. Bir satır nerede olduğunu, ne zaman olduğunu ve telefonun ne yaptığını — açık, cepte veya şarjda — hatırlar ve şimdiki seviye saat üzerinde bir aritmetiktir. Yüz oyuncu yüz zamanlayıcıya değil, yüz sayıya mal olur ve bir sunucu yeniden başlatması boyunca şarjda bırakılan bir telefon donmuş olarak değil, şarj olmuş olarak geri gelir.
İstemlerinizi birinin fotoğraf albümünün dışında tutmak
Section titled “İstemlerinizi birinin fotoğraf albümünün dışında tutmak”(Bu ve birlikte yaşamanın geri kalanı — ped, prop, eşya modu — kaynağınız onun yanında sayfasında toplanmıştır.)
Bir fotoğraf, çerçevenin tamamıdır. Deklanşöre basıldığı anda kaynağınızın çizdiği her şey — bir yardım istemi, bir marker etiketi, bir ilerleme çubuğu — fotoğrafın içindedir ve bu kaynak onu çizmenizi engelleyemez.
phoneCamera kendinizi durdurabilmeniz için vardır. Vizör açıldığı andan kapandığı ana kadar true’dur ve bir çizim döngüsündeki tek bir satır çözümün tamamıdır:
if LocalPlayer.state.phoneCamera then goto skip endTelefonun kendi HUD’u zaten yoldan çekilmiştir: Config.Apps.Camera.HideHud, kamera açık kaldığı sürece oyunun mini haritasını ve can çubuklarını gizler; böylece birinin çerçevelediği şey, aldığı şeydir.
El feneri bir flashlight state bag’idir; dolayısıyla diğer her client ışını o oyuncunun ped’i üzerinde çizer. Yalnızca telefon dışarıdayken parlar ve telefon gidince söner.
Client export’ları
Section titled “Client export’ları”exports.mic_phone:Open() / Close() / Toggle() / IsOpen()exports.mic_phone:CanOpen() --> ok, reasonexports.mic_phone:Restricted() --> 'Dead' | 'Cuffed' | 'Swimming' | … | nilexports.mic_phone:OpenApp('bank') / CloseApp()exports.mic_phone:GetNumber() / GetDevice() / HasPhone() / IsBooted()exports.mic_phone:IsInCall() / IsTablet() / SetTablet(true)exports.mic_phone:Notify({ app =, title =, body = })Buradaki hiçbir şey telefonun kendine uyguladığı kontrollerin ötesine geçmez. Open ve OpenApp, F1’e basan bir oyuncunun alacağı aynı reddi aynı nedenlerle alır — sahibi ölüyken bir kaynak kibarca istedi diye açılan bir telefon, kuralları olan bir telefon değildir. CanOpen ve Restricted, sormadan önce sorabilmeniz ve hiçbir şey yapmayan bir düğme sunmak yerine bir düğmeyi grileştirebilmeniz için vardır.
Anlam aynı olduğunda bag adları lb-phone’unkilerle eşleşir; böylece o telefona karşı yazılmış bir script bunu değişiklik yapmadan okur.